/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * */ /* * Copyright Likewise Software 2004-2008 * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. You should have received a copy of the GNU General * Public License along with this program. If not, see * . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Copyright (C) Likewise Software. All rights reserved. * * Module Name: * * main.c * * Abstract: * * Likewise Security and Authentication Subsystem (LSASS) * Driver for program to modify an exiting user * * Authors: * * Krishna Ganugapati (krishnag@likewisesoftware.com) * Sriram Nambakam (snambakam@likewisesoftware.com) */ #include "mod_user_includes.h" #define LW_PRINTF_STRING(x) ((x) ? (x) : "") static DWORD MapErrorCode( DWORD dwError ); static DWORD ModifyUser( PSTR pszLoginId, PDLINKEDLIST pTaskList ); static DWORD ParseArgs( int argc, char* argv[], PSTR* ppszLoginId, PDLINKEDLIST* ppTaskList ); static VOID FreeTasksInList( PVOID pTask, PVOID pUserData ); static VOID FreeTask( PUSER_MOD_TASK pTask ); static PSTR GetProgramName( PSTR pszFullProgramPath ); static VOID ShowUsage( PCSTR pszProgramName ); static BOOLEAN ValidateArgs( PCSTR pszLoginId, PDLINKEDLIST pTaskList ); static DWORD BuildUserModInfo( uid_t uid, PDLINKEDLIST pTaskList, PLSA_USER_MOD_INFO* ppUserModInfo ); static DWORD ReadPassword( PSTR* ppszPassword ); static DWORD LsaModUserMain( int argc, char* argv[] ) { DWORD dwError = 0; PDLINKEDLIST pTaskList = NULL; PSTR pszLoginId = NULL; size_t dwErrorBufferSize = 0; BOOLEAN bPrintOrigError = TRUE; if (geteuid() != 0) { fprintf(stderr, "This program requires super-user privileges.\n"); dwError = EACCES; BAIL_ON_LSA_ERROR(dwError); } dwError = ParseArgs(argc, argv, &pszLoginId, &pTaskList); BAIL_ON_LSA_ERROR(dwError); dwError = ModifyUser( pszLoginId, pTaskList); BAIL_ON_LSA_ERROR(dwError); cleanup: if (pTaskList) { LsaDLinkedListForEach(pTaskList, &FreeTasksInList, NULL); LsaDLinkedListFree(pTaskList); } LW_SAFE_FREE_STRING(pszLoginId); return dwError; error: dwError = MapErrorCode(dwError); dwErrorBufferSize = LwGetErrorString(dwError, NULL, 0); if (dwErrorBufferSize > 0) { DWORD dwError2 = 0; PSTR pszErrorBuffer = NULL; dwError2 = LwAllocateMemory( dwErrorBufferSize, (PVOID*)&pszErrorBuffer); if (!dwError2) { DWORD dwLen = LwGetErrorString(dwError, pszErrorBuffer, dwErrorBufferSize); if ((dwLen == dwErrorBufferSize) && !LW_IS_NULL_OR_EMPTY_STR(pszErrorBuffer)) { fprintf(stderr, "Failed to modify user. Error code %u (%s).\n%s\n", dwError, LW_PRINTF_STRING(LwWin32ExtErrorToName(dwError)), pszErrorBuffer); bPrintOrigError = FALSE; } } LW_SAFE_FREE_STRING(pszErrorBuffer); } if (bPrintOrigError) { fprintf(stderr, "Failed to modify user. Error code %u (%s).\n", dwError, LW_PRINTF_STRING(LwWin32ExtErrorToName(dwError))); } goto cleanup; } static DWORD ParseArgs( int argc, char* argv[], PSTR* ppszLoginId, PDLINKEDLIST* ppTaskList ) { typedef enum { PARSE_MODE_OPEN = 0, PARSE_MODE_ADD_TO_GROUPS, PARSE_MODE_REMOVE_FROM_GROUPS, PARSE_MODE_SET_EXPIRY_DATE, PARSE_MODE_SET_PRIMARY_GROUP, PARSE_MODE_SET_NT_PASSWORD_HASH, PARSE_MODE_SET_LM_PASSWORD_HASH, PARSE_MODE_SET_HOMEDIR, PARSE_MODE_SET_SHELL, PARSE_MODE_SET_GECOS, PARSE_MODE_DONE } ParseMode; DWORD dwError = 0; ParseMode parseMode = PARSE_MODE_OPEN; int iArg = 1; PSTR pArg = NULL; PDLINKEDLIST pTaskList = NULL; PUSER_MOD_TASK pTask = NULL; PSTR pszLoginId = NULL; PSTR pszPassword = NULL; do { pArg = argv[iArg++]; if (pArg == NULL || *pArg == '\0') { break; } switch(parseMode) { case PARSE_MODE_OPEN: { if (!strcmp(pArg, "--enable-user")) { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_EnableUser; dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); pTask = NULL; } else if (!strcmp(pArg, "--disable-user")) { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_DisableUser; dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); pTask = NULL; } else if ((strcmp(pArg, "--help") == 0) || (strcmp(pArg, "-h") == 0)) { ShowUsage(GetProgramName(argv[0])); exit(0); } else if (!strcmp(pArg, "--change-password-at-next-logon")) { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_ChangePasswordAtNextLogon; dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); pTask = NULL; } else if (!strcmp(pArg, "--set-password")) { fprintf(stdout, "New password: "); fflush(stdout); dwError = ReadPassword(&pszPassword); BAIL_ON_LSA_ERROR(dwError); fprintf(stdout, "\n"); dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_SetPassword; pTask->pszData = pszPassword; pszPassword = NULL; dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); pTask = NULL; } else if (!strcmp(pArg, "--unlock")) { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_UnlockUser; dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); pTask = NULL; } else if (!strcmp(pArg, "--password-never-expires")) { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_SetPasswordNeverExpires; dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); pTask = NULL; } else if (!strcmp(pArg, "--password-must-expire")) { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_SetPasswordMustExpire; dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); pTask = NULL; } else if (!strcmp(pArg, "--add-to-groups")) { parseMode = PARSE_MODE_ADD_TO_GROUPS; } else if (!strcmp(pArg, "--remove-from-groups")) { parseMode = PARSE_MODE_REMOVE_FROM_GROUPS; } else if (!strcmp(pArg, "--set-nt-password-hash")) { parseMode = PARSE_MODE_SET_NT_PASSWORD_HASH; } else if (!strcmp(pArg, "--set-lm-password-hash")) { parseMode = PARSE_MODE_SET_LM_PASSWORD_HASH; } else if (!strcmp(pArg, "--set-homedir")) { parseMode = PARSE_MODE_SET_HOMEDIR; } else if (!strcmp(pArg, "--set-shell")) { parseMode = PARSE_MODE_SET_SHELL; } else if (!strcmp(pArg, "--set-gecos")) { parseMode = PARSE_MODE_SET_GECOS; } else if (!strcmp(pArg, "--set-account-expiry-date")) { parseMode = PARSE_MODE_SET_EXPIRY_DATE; } else if (!strcmp(pArg, "--set-primary-group")) { parseMode = PARSE_MODE_SET_PRIMARY_GROUP; } else { dwError = LwAllocateString(pArg, &pszLoginId); BAIL_ON_LSA_ERROR(dwError); parseMode = PARSE_MODE_DONE; } break; } case PARSE_MODE_REMOVE_FROM_GROUPS: { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_RemoveFromGroups; dwError = LwAllocateString(pArg, &pTask->pszData); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); parseMode = PARSE_MODE_OPEN; break; } case PARSE_MODE_ADD_TO_GROUPS: { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_AddToGroups; dwError = LwAllocateString(pArg, &pTask->pszData); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); parseMode = PARSE_MODE_OPEN; break; } case PARSE_MODE_SET_NT_PASSWORD_HASH: { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_SetNtPasswordHash; dwError = LwAllocateString(pArg, &pTask->pszData); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); parseMode = PARSE_MODE_OPEN; break; } case PARSE_MODE_SET_LM_PASSWORD_HASH: { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_SetLmPasswordHash; dwError = LwAllocateString(pArg, &pTask->pszData); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); parseMode = PARSE_MODE_OPEN; break; } case PARSE_MODE_SET_EXPIRY_DATE: { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_SetExpiryDate; dwError = LwAllocateString(pArg, &pTask->pszData); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); parseMode = PARSE_MODE_OPEN; break; } case PARSE_MODE_SET_PRIMARY_GROUP: { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_SetPrimaryGroup; dwError = LwAllocateString(pArg, &pTask->pszData); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); parseMode = PARSE_MODE_OPEN; break; } case PARSE_MODE_SET_HOMEDIR: { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_SetHomedir; dwError = LwAllocateString(pArg, &pTask->pszData); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); parseMode = PARSE_MODE_OPEN; break; } case PARSE_MODE_SET_SHELL: { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_SetShell; dwError = LwAllocateString(pArg, &pTask->pszData); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); parseMode = PARSE_MODE_OPEN; break; } case PARSE_MODE_SET_GECOS: { dwError = LwAllocateMemory(sizeof(USER_MOD_TASK), (PVOID*)&pTask); BAIL_ON_LSA_ERROR(dwError); pTask->taskType = UserModTask_SetGecos; dwError = LwAllocateString(pArg, &pTask->pszData); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDLinkedListAppend(&pTaskList, pTask); BAIL_ON_LSA_ERROR(dwError); parseMode = PARSE_MODE_OPEN; break; } case PARSE_MODE_DONE: { ShowUsage(GetProgramName(argv[0])); exit(1); } } } while (iArg < argc); if (parseMode != PARSE_MODE_OPEN && parseMode != PARSE_MODE_DONE) { ShowUsage(GetProgramName(argv[0])); exit(1); } if (!ValidateArgs(pszLoginId, pTaskList)) { ShowUsage(GetProgramName(argv[0])); exit(1); } *ppszLoginId = pszLoginId; *ppTaskList = pTaskList; cleanup: LW_SAFE_FREE_STRING (pszPassword); return dwError; error: *ppTaskList = NULL; if (pTaskList) { LsaDLinkedListForEach(pTaskList, FreeTasksInList, NULL); LsaDLinkedListFree(pTaskList); } if (pTask) { FreeTask(pTask); } LW_SAFE_FREE_STRING(pszLoginId); goto cleanup; } static BOOLEAN ValidateArgs( PCSTR pszLoginId, PDLINKEDLIST pTaskList ) { BOOLEAN bValid = FALSE; PDLINKEDLIST pListMember = NULL; BOOLEAN bEnableUser = FALSE; BOOLEAN bDisableUser = FALSE; BOOLEAN bSetChangePasswordAtNextLogon = FALSE; BOOLEAN bSetPasswordNeverExpires = FALSE; BOOLEAN bSetPassword = FALSE; PSTR pszNtPasswordHash = NULL; PSTR pszLmPasswordHash = NULL; for (pListMember = pTaskList; pListMember; pListMember = pListMember->pNext) { PUSER_MOD_TASK pTask = (PUSER_MOD_TASK)pListMember->pItem; if (pTask) { switch(pTask->taskType) { case UserModTask_EnableUser: { bEnableUser = TRUE; break; } case UserModTask_DisableUser: { bDisableUser = TRUE; break; } case UserModTask_SetPasswordNeverExpires: { bSetPasswordNeverExpires = TRUE; break; } case UserModTask_ChangePasswordAtNextLogon: { bSetChangePasswordAtNextLogon = TRUE; break; } case UserModTask_SetNtPasswordHash: { pszNtPasswordHash = pTask->pszData; break; } case UserModTask_SetLmPasswordHash: { pszLmPasswordHash = pTask->pszData; break; } case UserModTask_SetPassword: { bSetPassword = TRUE; break; } default: break; } } } if (bEnableUser && bDisableUser) { fprintf(stderr, "Error: Both --enable-user and --disable-user cannot be specified.\n"); goto cleanup; } if (bSetPasswordNeverExpires && bSetChangePasswordAtNextLogon) { fprintf(stderr, "Error: The options --password-never-expires and\n"); fprintf(stderr, " --change-password-at-next-logon cannot be specified together.\n"); goto cleanup; } if (LW_IS_NULL_OR_EMPTY_STR(pszLoginId)) { fprintf(stderr, "Error: A valid user id or user login id must be specified.\n"); goto cleanup; } if (pszNtPasswordHash && !(strlen(pszNtPasswordHash) == 32 || strlen(pszNtPasswordHash) == 0)) { fprintf(stderr, "Error: NT password hash must be zero or 32 characters long.\n"); goto cleanup; } if (pszLmPasswordHash && !(strlen(pszLmPasswordHash) == 32 || strlen(pszLmPasswordHash) == 0)) { fprintf(stderr, "Error: LM password hash must be zero or 32 characters long.\n"); goto cleanup; } if (bSetPassword && pszNtPasswordHash) { fprintf(stderr, "Error: the password and NT password hash cannot be specified together.\n"); goto cleanup; } if (bSetPassword && pszLmPasswordHash) { fprintf(stderr, "Error: the password and LM password hash cannot be specified together.\n"); goto cleanup; } bValid = TRUE; cleanup: return bValid; } static VOID FreeTasksInList( PVOID pTask, PVOID pUserData ) { if (pTask) { FreeTask((PUSER_MOD_TASK)pTask); } } static VOID FreeTask( PUSER_MOD_TASK pTask ) { LW_SAFE_FREE_STRING(pTask->pszData); LwFreeMemory(pTask); } static PSTR GetProgramName( PSTR pszFullProgramPath ) { if (pszFullProgramPath == NULL || *pszFullProgramPath == '\0') { return NULL; } // start from end of the string PSTR pszNameStart = pszFullProgramPath + strlen(pszFullProgramPath); do { if (*(pszNameStart - 1) == '/') { break; } pszNameStart--; } while (pszNameStart != pszFullProgramPath); return pszNameStart; } static VOID ShowUsage( PCSTR pszProgramName ) { fprintf(stdout, "Usage: %s {modification options} ( user login id | uid )\n\n", pszProgramName); fprintf(stdout, "\nModification options:\n"); fprintf(stdout, "{ --help }\n"); fprintf(stdout, "{ --disable-user | --enable-user }\n"); fprintf(stdout, "{ --unlock }\n"); fprintf(stdout, "{ --change-password-at-next-logon }\n"); fprintf(stdout, "{ --password-never-expires }\n"); fprintf(stdout, "{ --password-must-expire }\n"); fprintf(stdout, "{ --add-to-groups nt4-style-group-name }\n"); fprintf(stdout, "{ --remove-from-groups nt4-style-group-name }\n"); fprintf(stdout, "{ --set-nt-password-hash password-hash-hex }\n"); fprintf(stdout, "{ --set-lm-password-hash password-hash-hex }\n"); fprintf(stdout, "{ --set-homedir home-directory }\n"); fprintf(stdout, "{ --set-shell shell }\n"); fprintf(stdout, "{ --set-gecos gecos }\n"); fprintf(stdout, "{ --set-account-expiry expiry-date (YYYY-MM-DD format) }\n"); fprintf(stdout, "{ --set-primary-group gid }\n"); fprintf(stdout, "{ --set-password password }\n"); fprintf(stdout, "\nNotes:\n"); fprintf(stdout, "a) Set the expiry-date to 0 for an account that must never expire.\n"); fprintf(stdout, "b) If both --remove-from-group and --add-to-group are specified,\n"); fprintf(stdout, " the user is removed from the specified group first.\n"); fprintf(stdout, "c) The options ""--change-password-at-next-logon"" and \n"); fprintf(stdout, " ""--password-never-expires"" cannot be set simultaneously.\n"); } static DWORD ModifyUser( PSTR pszLoginId, PDLINKEDLIST pTaskList ) { DWORD dwError = 0; PLSA_USER_MOD_INFO pUserModInfo = NULL; uid_t uid = 0; int nRead = 0; PVOID pUserInfo = NULL; DWORD dwUserInfoLevel = 0; HANDLE hLsaConnection = (HANDLE)NULL; BAIL_ON_INVALID_STRING(pszLoginId); dwError = LsaOpenServer(&hLsaConnection); BAIL_ON_LSA_ERROR(dwError); nRead = sscanf(pszLoginId, "%u", (unsigned int*)&uid); if ((nRead == EOF) || (nRead == 0)) { dwError = LsaFindUserByName( hLsaConnection, pszLoginId, dwUserInfoLevel, &pUserInfo); BAIL_ON_LSA_ERROR(dwError); uid = ((PLSA_USER_INFO_0)pUserInfo)->uid; LsaFreeUserInfo(dwUserInfoLevel, pUserInfo); pUserInfo = NULL; } dwError = BuildUserModInfo( uid, pTaskList, &pUserModInfo); BAIL_ON_LSA_ERROR(dwError); dwError = LsaModifyUser( hLsaConnection, pUserModInfo); BAIL_ON_LSA_ERROR(dwError); fprintf(stdout, "Successfully modified user %s\n", pszLoginId); cleanup: if (pUserModInfo) { LsaFreeUserModInfo(pUserModInfo); } if (pUserInfo) { LsaFreeUserInfo(dwUserInfoLevel, pUserInfo); } if (hLsaConnection != (HANDLE)NULL) { LsaCloseServer(hLsaConnection); } return dwError; error: goto cleanup; } static DWORD BuildUserModInfo( uid_t uid, PDLINKEDLIST pTaskList, PLSA_USER_MOD_INFO* ppUserModInfo ) { DWORD dwError = 0; PDLINKEDLIST pListMember = pTaskList; PLSA_USER_MOD_INFO pUserModInfo = NULL; dwError = LsaBuildUserModInfo(uid, &pUserModInfo); BAIL_ON_LSA_ERROR(dwError); for (; pListMember; pListMember = pListMember->pNext) { PUSER_MOD_TASK pTask = (PUSER_MOD_TASK)pListMember->pItem; switch(pTask->taskType) { case UserModTask_EnableUser: { dwError = LsaModifyUser_EnableUser(pUserModInfo, TRUE); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_DisableUser: { dwError = LsaModifyUser_DisableUser(pUserModInfo, TRUE); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_UnlockUser: { dwError = LsaModifyUser_Unlock(pUserModInfo, TRUE); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_ChangePasswordAtNextLogon: { dwError = LsaModifyUser_ChangePasswordAtNextLogon(pUserModInfo, TRUE); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_AddToGroups: { dwError = LsaModifyUser_AddToGroups(pUserModInfo, pTask->pszData); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_RemoveFromGroups: { dwError = LsaModifyUser_RemoveFromGroups(pUserModInfo, pTask->pszData); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_SetPasswordNeverExpires: { dwError = LsaModifyUser_SetPasswordNeverExpires(pUserModInfo, TRUE); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_SetPasswordMustExpire: { dwError = LsaModifyUser_SetPasswordMustExpire(pUserModInfo, TRUE); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_SetNtPasswordHash: { dwError = LsaModifyUser_SetNtPasswordHash(pUserModInfo, pTask->pszData); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_SetLmPasswordHash: { dwError = LsaModifyUser_SetLmPasswordHash(pUserModInfo, pTask->pszData); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_SetExpiryDate: { dwError = LsaModifyUser_SetExpiryDate(pUserModInfo, pTask->pszData); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_SetPrimaryGroup: { dwError = LsaModifyUser_SetPrimaryGroup(pUserModInfo, pTask->pszData); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_SetHomedir: { dwError = LsaModifyUser_SetHomedir(pUserModInfo, pTask->pszData); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_SetShell: { dwError = LsaModifyUser_SetShell(pUserModInfo, pTask->pszData); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_SetGecos: { dwError = LsaModifyUser_SetGecos(pUserModInfo, pTask->pszData); BAIL_ON_LSA_ERROR(dwError); break; } case UserModTask_SetPassword: { dwError = LsaModifyUser_SetPassword(pUserModInfo, pTask->pszData); BAIL_ON_LSA_ERROR(dwError); break; } } } *ppUserModInfo = pUserModInfo; cleanup: return dwError; error: *ppUserModInfo = NULL; if (pUserModInfo) { LsaFreeUserModInfo(pUserModInfo); } goto cleanup; } static DWORD MapErrorCode( DWORD dwError ) { DWORD dwError2 = dwError; switch (dwError) { case ECONNREFUSED: case ENETUNREACH: case ETIMEDOUT: dwError2 = LW_ERROR_LSA_SERVER_UNREACHABLE; break; default: break; } return dwError2; } static DWORD ReadPassword( PSTR* ppszPassword ) { DWORD dwError = 0; CHAR szBuf[129]; DWORD idx = 0; struct termios old, new; CHAR ch; memset(szBuf, 0, sizeof(szBuf)); tcgetattr(0, &old); memcpy(&new, &old, sizeof(struct termios)); new.c_lflag &= ~(ECHO); tcsetattr(0, TCSANOW, &new); while ( (idx < 128) ) { if (read(0, &ch, 1)) { if (ch != '\n') { szBuf[idx++] = ch; } else { break; } } else { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(dwError); } } if (idx == 128) { dwError = LwMapErrnoToLwError(ENOBUFS); BAIL_ON_LSA_ERROR(dwError); } if (idx > 0) { dwError = LwAllocateString(szBuf, ppszPassword); BAIL_ON_LSA_ERROR(dwError); } else { *ppszPassword = NULL; } error: tcsetattr(0, TCSANOW, &old); return dwError; } int mod_user_main( int argc, char* argv[] ) { return LsaModUserMain(argc, argv); } /* local variables: mode: c c-basic-offset: 4 indent-tabs-mode: nil tab-width: 4 end: */