/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * * -*- mode: c, c-basic-offset: 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 */ #include "domainjoin.h" #include "djdistroinfo.h" #include "djsshconf.h" #include "djpamconf.h" #include "djtimemgmt.h" #include "djcli.h" #include "djfirewall.h" #include "djauditing.h" #include "ctprocutils.h" #include "lwexc.h" #define GCE(x) GOTO_CLEANUP_ON_CENTERROR((x)) CENTERROR ParseUInt(PCSTR in, unsigned int *out) { CENTERROR ceError = CENTERROR_SUCCESS; PSTR endPtr; *out = strtoul(in, &endPtr, 10); if(*endPtr != '\0') { GCE(ceError = CENTERROR_INVALID_OPTION_VALUE); } cleanup: return ceError; } static void ShowUsage() { fprintf(stdout, "usage: domainjoin-cli [options] command [args...]\n\n"); fprintf(stdout, " where options are:\n\n"); fprintf(stdout, " --help Display this help information.\n"); fprintf(stdout, " --help-internal Display help for debug commands\n"); fprintf(stdout, " --log {.|path} Log to a file (or \".\" to log\n" " to console).\n"); fprintf(stdout, " --loglevel {error|warning|info|verbose} Adjusts how much logging is\n" " produced by domainjoin.\n"); fprintf(stdout, " --nodcerpcd prevents dcerpcd from being\n" " started, along with any daemons\n" " that depend on it.\n"); fprintf(stdout, "\n"); fprintf(stdout, " and commands are:\n\n"); fprintf(stdout, " query\n"); fprintf(stdout, " setname \n"); fprintf(stdout, " join [--notimesync] [--enable --disable ...] [--ou ] []\n"); fprintf(stdout, " join [--advanced] --preview [--ou ] \n"); fprintf(stdout, " join [--ou ] --details \n"); fprintf(stdout, " leave [--enable --disable ...] [user name] [password]\n"); fprintf(stdout, " leave [--advanced] --preview [user name] [password]\n"); fprintf(stdout, " leave --details \n\n"); fprintf(stdout, " Example:\n\n"); fprintf(stdout, " domainjoin-cli join likewisedemo.com Administrator\n\n"); } static void ShowUsageInternal() { ShowUsage(); fprintf(stdout, " Internal debug commands:\n"); fprintf(stdout, " fixfqdn\n"); fprintf(stdout, " configure { --enable | --disable } pam [--testprefix ]\n"); fprintf(stdout, " configure { --enable | --disable } nsswitch [--testprefix ]\n"); fprintf(stdout, " configure { --enable | --disable } ssh [--testprefix ]\n"); fprintf(stdout, " configure { --enable | --disable } [--testprefix ] [--long ] [--short ] krb5\n"); fprintf(stdout, " configure { --enable | --disable } firewall [--testprefix ]\n"); fprintf(stdout, " configure { --enable | --disable } eventfwdd\n"); fprintf(stdout, " configure { --enable | --disable } reapsysld\n"); fprintf(stdout, " get_os_type\n"); fprintf(stdout, " get_arch\n"); fprintf(stdout, " get_distro\n"); fprintf(stdout, " get_distro_version\n"); fprintf(stdout, " sync_time \n"); fprintf(stdout, " raise_error \n"); fprintf(stdout, "\n"); } static CENTERROR FillMissingPassword( PCSTR username, PSTR* ppszPassword ) { CENTERROR ceError = CENTERROR_SUCCESS; PSTR pszPassword = NULL; PCSTR pszEnvPassword = NULL; pszEnvPassword = getenv("PASSWORD"); if (pszEnvPassword == NULL) { fprintf(stdout, "%s's password: ",username); fflush(stdout); ceError = GetPassword(&pszPassword); BAIL_ON_CENTERIS_ERROR(ceError); fprintf(stdout, "\n"); } else { DJ_LOG_WARNING("Retrieved password from envionmental variable"); ceError = CTStrdup(pszEnvPassword, &pszPassword); BAIL_ON_CENTERIS_ERROR(ceError); } if (!IsNullOrEmptyString(pszPassword)) { *ppszPassword = pszPassword; pszPassword = NULL; } error: if (pszPassword) CTFreeString(pszPassword); return ceError; } BOOLEAN GetEnableBoolean(EnableType dwEnable) { PDOMAINJOININFO pDomainJoinInfo = NULL; if(dwEnable == ENABLE_TYPE_AUTO) { LW_TRY(NULL, QueryInformation(&pDomainJoinInfo, &LW_EXC)); if(IsNullOrEmptyString(pDomainJoinInfo->pszDomainName)) dwEnable = ENABLE_TYPE_DISABLE; else dwEnable = ENABLE_TYPE_ENABLE; } cleanup: if(pDomainJoinInfo != NULL) FreeDomainJoinInfo(pDomainJoinInfo); return dwEnable == ENABLE_TYPE_ENABLE; } void PrintWarning(const JoinProcessOptions *options, const char *title, const char *message) { PSTR wrapped = NULL; int columns; if(!CENTERROR_IS_OK(CTGetTerminalWidth(fileno(stdout), &columns))) columns = -1; //This function doesn't return a CENTERROR, so we have to recover as much //as possible. if(CENTERROR_IS_OK(CTWordWrap(message, &wrapped, 4, columns))) fprintf(stdout, "Warning: %s\n%s\n\n", title, wrapped); else fprintf(stdout, "Warning: %s\n%s\n\n", title, message); CT_SAFE_FREE_STRING(wrapped); DJ_LOG_WARNING("%s\n%s", title, message); } void PrintModuleState(ModuleState *state) { char resultChar; if(state->lastResult != FullyConfigured && state->lastResult != CannotConfigure) { fprintf(stdout, "[%c] ", state->runModule? 'X' : ' '); } else { fprintf(stdout, " "); } switch(state->lastResult) { default: case NotApplicable: //This case should not occur resultChar = 'E'; break; case FullyConfigured: resultChar = 'F'; break; case SufficientlyConfigured: resultChar = 'S'; break; case NotConfigured: resultChar = 'N'; break; case CannotConfigure: //This is distinguishable from NotConfigured because the //checkbox to the left doesn't appear. resultChar = 'N'; break; } fprintf(stdout, "[%c] %-15s- %s\n", resultChar, state->module->shortName, state->module->longName); } void PrintStateKey() { fprintf(stdout, "\n" "Key to flags\n" "[F]ully configured - the system is already configured for this step\n" "[S]ufficiently configured - the system meets the minimum configuration\n" " requirements for this step\n" "[N]ecessary - this step must be run or manually performed.\n" "\n" "[X] - this step is enabled and will make changes\n" "[ ] - this step is disabled and will not make changes\n"); } void PrintJoinHeader(const JoinProcessOptions *options, LWException **exc) { PSTR fqdn = NULL; PDOMAINJOININFO pDomainJoinInfo = NULL; PCSTR domain; if(options->joiningDomain) { LW_CLEANUP_CTERR(exc, DJGetFinalFqdn(options, &fqdn)); fprintf(stdout, "Joining to AD Domain: %s\n" "With Computer DNS Name: %s\n\n", options->domainName, fqdn); } else { LW_TRY(exc, QueryInformation(&pDomainJoinInfo, &LW_EXC)); domain = pDomainJoinInfo->pszDomainName; if(domain == NULL) domain = "(unknown)"; fprintf(stdout, "Leaving AD Domain: %s\n", domain); } cleanup: CT_SAFE_FREE_STRING(fqdn); } void PrintModuleStates(BOOLEAN showTristate, JoinProcessOptions *options) { size_t i; if(showTristate) { for(i = 0; i < options->moduleStates.size; i++) { PrintModuleState(DJGetModuleState(options, i)); } PrintStateKey(); } else { fprintf(stdout, "The following stages are currently configured to be run during the domain join:\n"); for(i = 0; i < options->moduleStates.size; i++) { ModuleState *state = DJGetModuleState(options, i); if(state->runModule) { fprintf(stdout, "%-15s- %s\n", state->module->shortName, state->module->longName); } } } } void DoJoin(int argc, char **argv, int columns, LWException **exc) { JoinProcessOptions options; BOOLEAN advanced = FALSE; BOOLEAN preview = FALSE; DynamicArray enableModules, disableModules; DynamicArray detailModules; size_t i; int passwordIndex = -1; PSTR moduleDetails = NULL; PSTR wrapped = NULL; DJZeroJoinProcessOptions(&options); memset(&enableModules, 0, sizeof(enableModules)); memset(&disableModules, 0, sizeof(disableModules)); memset(&detailModules, 0, sizeof(detailModules)); while(argc > 0 && CTStrStartsWith(argv[0], "--")) { if(!strcmp(argv[0], "--advanced")) advanced = TRUE; else if(!strcmp(argv[0], "--preview")) preview = TRUE; else if(!strcmp(argv[0], "--ignore-firewall-ntp")) { printf("Warning: --ignore-firewall-ntp is deprecated. This behavior is now default.\n"); } else if(!strcmp(argv[0], "--ignore-pam")) options.ignorePam = TRUE; else if(!strcmp(argv[0], "--notimesync")) options.disableTimeSync = TRUE; else if(!strcmp(argv[0], "--nohosts")) { PCSTR module = "hostname"; LW_CLEANUP_CTERR(exc, CTArrayAppend(&disableModules, sizeof(PCSTR), &module, 1)); } else if(argc < 2) { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } else if(!strcmp(argv[0], "--enable")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&enableModules, sizeof(PCSTR), &argv[1], 1)); argv++; argc--; } else if(!strcmp(argv[0], "--disable")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&disableModules, sizeof(PCSTR), &argv[1], 1)); argv++; argc--; } else if(!strcmp(argv[0], "--details")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&detailModules, sizeof(PCSTR), &argv[1], 1)); argv++; argc--; } else if(!strcmp(argv[0], "--ou")) { CT_SAFE_FREE_STRING(options.ouName); LW_CLEANUP_CTERR(exc, CTStrdup(argv[1], &options.ouName)); argv++; argc--; } else { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } argv++; argc--; } if(argc == 3) { LW_CLEANUP_CTERR(exc, CTStrdup(argv[2], &options.password)); passwordIndex = 2; } // The join username is not required in preview or details mode. else if(argc == 1 && (preview || detailModules.size != 0) ) ; else if(argc != 2) { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } options.joiningDomain = TRUE; DJ_LOG_INFO("Domainjoin invoked with %d arg(s) to the join command:", argc); for(i = 0; i < argc; i++) { DJ_LOG_INFO(" [%s]", i == passwordIndex ? "" : argv[i]); } LW_CLEANUP_CTERR(exc, CTStrdup( argv[0], &options.domainName)); if(argc > 1) { LW_CLEANUP_CTERR(exc, CTStrdup(argv[1], &options.username)); } options.warningCallback = PrintWarning; options.showTraces = advanced; LW_CLEANUP_CTERR(exc, DJGetComputerName(&options.computerName)); LW_TRY(exc, DJInitModuleStates(&options, &LW_EXC)); for(i = 0; i < enableModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &enableModules, i, sizeof(PCSTR)); if(CTArrayFindString(&disableModules, module) != -1) { LW_RAISE_EX(exc, CENTERROR_INVALID_OPTION_VALUE, "Module already specified", "The module '%s' is listed as being disabled and enabled", module); goto cleanup; } LW_TRY(exc, DJEnableModule(&options, module, TRUE, &LW_EXC)); } for(i = 0; i < disableModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &disableModules, i, sizeof(PCSTR)); if(CTArrayFindString(&enableModules, module) != -1) { LW_RAISE_EX(exc, CENTERROR_INVALID_OPTION_VALUE, "Module already specified", "The module '%s' is listed as being disabled and enabled", module); goto cleanup; } LW_TRY(exc, DJEnableModule(&options, module, FALSE, &LW_EXC)); } for(i = 0; i < detailModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &detailModules, i, sizeof(PCSTR)); ModuleState *state = DJGetModuleStateByName(&options, module); if(state == NULL) { LW_RAISE_EX(exc, CENTERROR_INVALID_PARAMETER, "Unable to find module.", "Please check the spelling of '%s'. This module cannot be found", module); goto cleanup; } PrintModuleState(state); } if(detailModules.size > 0) { PrintStateKey(); } for(i = 0; i < detailModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &detailModules, i, sizeof(PCSTR)); ModuleState *state = DJGetModuleStateByName(&options, module); CT_SAFE_FREE_STRING(moduleDetails); CT_SAFE_FREE_STRING(wrapped); LW_TRY(exc, moduleDetails = state->module->GetChangeDescription(&options, &LW_EXC)); LW_CLEANUP_CTERR(exc, CTWordWrap(moduleDetails, &wrapped, 4, columns)); fprintf(stdout, "\nDetails for '%s':\n%s\n", state->module->longName, wrapped); } if(detailModules.size > 0) goto cleanup; LW_TRY(exc, PrintJoinHeader(&options, &LW_EXC)); if(preview) { PrintModuleStates(advanced, &options); if(!advanced) LW_TRY(exc, DJCheckRequiredEnabled(&options, &LW_EXC)); goto cleanup; } LW_TRY(exc, DJCheckRequiredEnabled(&options, &LW_EXC)); if (IsNullOrEmptyString(options.password)) { CT_SAFE_FREE_STRING(options.password); LW_CLEANUP_CTERR(exc, FillMissingPassword(options.username, &options.password)); } LW_TRY(exc, DJRunJoinProcess(&options, &LW_EXC)); fprintf(stdout, "SUCCESS\n"); cleanup: DJFreeJoinProcessOptions(&options); CTArrayFree(&enableModules); CTArrayFree(&disableModules); CTArrayFree(&detailModules); CT_SAFE_FREE_STRING(moduleDetails); CT_SAFE_FREE_STRING(wrapped); } void DoLeaveNew(int argc, char **argv, int columns, LWException **exc) { JoinProcessOptions options; BOOLEAN advanced = FALSE; BOOLEAN preview = FALSE; DynamicArray enableModules, disableModules; DynamicArray detailModules; size_t i; PSTR moduleDetails = NULL; PSTR wrapped = NULL; int passwordIndex = -1; DJZeroJoinProcessOptions(&options); memset(&enableModules, 0, sizeof(enableModules)); memset(&disableModules, 0, sizeof(disableModules)); memset(&detailModules, 0, sizeof(detailModules)); while(argc > 0 && CTStrStartsWith(argv[0], "--")) { if(!strcmp(argv[0], "--advanced")) advanced = TRUE; else if(!strcmp(argv[0], "--preview")) preview = TRUE; else if(argc < 2) { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } else if(!strcmp(argv[0], "--enable")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&enableModules, sizeof(PCSTR *), &argv[1], 1)); argv++; argc--; } else if(!strcmp(argv[0], "--disable")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&disableModules, sizeof(PCSTR *), &argv[1], 1)); argv++; argc--; } else if(!strcmp(argv[0], "--details")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&detailModules, sizeof(PCSTR *), &argv[1], 1)); argv++; argc--; } else { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } argv++; argc--; } if(argc == 2) { LW_CLEANUP_CTERR(exc, CTStrdup(argv[1], &options.password)); passwordIndex = 1; } else if(argc > 2) { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } options.joiningDomain = FALSE; DJ_LOG_INFO("Domainjoin invoked with %d arg(s) to the leave command:", argc); for(i = 0; i < argc; i++) { DJ_LOG_INFO(" [%s]", i == passwordIndex ? "" : argv[i]); } if(argc > 0) { LW_CLEANUP_CTERR(exc, CTStrdup(argv[0], &options.username)); } options.warningCallback = PrintWarning; options.showTraces = advanced; LW_CLEANUP_CTERR(exc, DJGetComputerName(&options.computerName)); LW_TRY(exc, DJInitModuleStates(&options, &LW_EXC)); for(i = 0; i < enableModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &enableModules, i, sizeof(PCSTR)); if(CTArrayFindString(&disableModules, module) != -1) { LW_RAISE_EX(exc, CENTERROR_INVALID_OPTION_VALUE, "Module already specified", "The module '%s' is listed as being disabled and enabled", module); goto cleanup; } LW_TRY(exc, DJEnableModule(&options, module, TRUE, &LW_EXC)); } for(i = 0; i < disableModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &disableModules, i, sizeof(PCSTR)); if(CTArrayFindString(&enableModules, module) != -1) { LW_RAISE_EX(exc, CENTERROR_INVALID_OPTION_VALUE, "Module already specified", "The module '%s' is listed as being disabled and enabled", module); goto cleanup; } LW_TRY(exc, DJEnableModule(&options, module, FALSE, &LW_EXC)); } for(i = 0; i < detailModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &detailModules, i, sizeof(PCSTR)); ModuleState *state = DJGetModuleStateByName(&options, module); if(state == NULL) { LW_RAISE_EX(exc, CENTERROR_INVALID_PARAMETER, "Unable to find module.", "Please check the spelling of '%s'. This module cannot be found", module); goto cleanup; } PrintModuleState(state); } if(detailModules.size > 0) { PrintStateKey(); } for(i = 0; i < detailModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &detailModules, i, sizeof(PCSTR)); ModuleState *state = DJGetModuleStateByName(&options, module); CT_SAFE_FREE_STRING(moduleDetails); CT_SAFE_FREE_STRING(wrapped); LW_TRY(exc, moduleDetails = state->module->GetChangeDescription(&options, &LW_EXC)); LW_CLEANUP_CTERR(exc, CTWordWrap(moduleDetails, &wrapped, 4, columns)); fprintf(stdout, "\nDetails for '%s':\n%s\n", state->module->longName, wrapped); } if(detailModules.size > 0) goto cleanup; LW_TRY(exc, PrintJoinHeader(&options, &LW_EXC)); if(preview) { PrintModuleStates(advanced, &options); if(!advanced) LW_TRY(exc, DJCheckRequiredEnabled(&options, &LW_EXC)); goto cleanup; } LW_TRY(exc, DJCheckRequiredEnabled(&options, &LW_EXC)); if (options.username != NULL && IsNullOrEmptyString(options.password)) { CT_SAFE_FREE_STRING(options.password); LW_CLEANUP_CTERR(exc, FillMissingPassword(options.username, &options.password)); } LW_TRY(exc, DJRunJoinProcess(&options, &LW_EXC)); fprintf(stdout, "SUCCESS\n"); cleanup: DJFreeJoinProcessOptions(&options); CTArrayFree(&enableModules); CTArrayFree(&disableModules); CTArrayFree(&detailModules); CT_SAFE_FREE_STRING(moduleDetails); CT_SAFE_FREE_STRING(wrapped); } #ifndef ENABLE_MINIMAL void DoConfigure(int argc, char **argv, LWException **exc) { EnableType dwEnable = ENABLE_TYPE_AUTO; PCSTR testPrefix = NULL; PCSTR longDomain = NULL; PCSTR shortDomain = NULL; while(argc > 0 && CTStrStartsWith(argv[0], "--")) { if(!strcmp(argv[0], "--autoenable")) dwEnable = ENABLE_TYPE_AUTO; else if(!strcmp(argv[0], "--enable")) dwEnable = ENABLE_TYPE_ENABLE; else if(!strcmp(argv[0], "--disable")) dwEnable = ENABLE_TYPE_DISABLE; else if(argc < 2) { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } else if(!strcmp(argv[0], "--testprefix")) { testPrefix = argv[1]; argv++; argc--; } else if(!strcmp(argv[0], "--long")) { longDomain = argv[1]; argv++; argc--; } else if(!strcmp(argv[0], "--short")) { shortDomain = argv[1]; argv++; argc--; } else { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } argv++; argc--; } if(argc < 1) { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } if(!strcmp(argv[0], "pam")) LW_TRY(exc, DJNewConfigurePamForADLogin(testPrefix, NULL, PrintWarning, GetEnableBoolean(dwEnable), &LW_EXC)); else if(!strcmp(argv[0], "nsswitch")) LW_CLEANUP_CTERR(exc, DJConfigureNameServiceSwitch(testPrefix, GetEnableBoolean(dwEnable))); else if(!strcmp(argv[0], "ssh")) LW_TRY(exc, DJConfigureSshForADLogin(testPrefix, GetEnableBoolean(dwEnable), NULL, &LW_EXC)); else if(!strcmp(argv[0], "krb5")) LW_CLEANUP_CTERR(exc, DJModifyKrb5Conf(testPrefix, GetEnableBoolean(dwEnable), longDomain, shortDomain, NULL)); else if(!strcmp(argv[0], "eventfwdd")) LW_CLEANUP_CTERR(exc, DJConfigureEventFwd(testPrefix, GetEnableBoolean(dwEnable))); else if(!strcmp(argv[0], "reapsysld")) LW_CLEANUP_CTERR(exc, DJConfigureReapSyslog(testPrefix, GetEnableBoolean(dwEnable))); else { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } fprintf(stdout, "SUCCESS\n"); cleanup: ; } #endif void DoGetDistroInfo(int argc, char **argv, LWException **exc) { PSTR str = NULL; PCSTR requestType = argv[0]; PCSTR testPrefix = NULL; DistroInfo distro = {0}; argc--; argv++; if(argc > 0 && !strcmp(argv[0], "--testprefix")) { testPrefix = argv[1]; argv += 2; argc -= 2; } if(argc > 0) { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } LW_CLEANUP_CTERR(exc, DJGetDistroInfo(testPrefix, &distro)); if(!strcmp(requestType, "get_os_type")) { LW_CLEANUP_CTERR(exc, DJGetOSString(distro.os, &str)); } else if(!strcmp(requestType, "get_arch")) { LW_CLEANUP_CTERR(exc, DJGetArchString(distro.arch, &str)); } else if(!strcmp(requestType, "get_distro")) { LW_CLEANUP_CTERR(exc, DJGetDistroString(distro.distro, &str)); } else if(!strcmp(requestType, "get_distro_version")) { LW_CLEANUP_CTERR(exc, CTStrdup(distro.version, &str)); } else { LW_RAISE(exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } fprintf(stdout, "%s\n", str); cleanup: DJFreeDistroInfo(&distro); CT_SAFE_FREE_STRING(str); } int main( int argc, char* argv[] ) { LWException *exc = NULL; int columns; PSTR pszLogFilePath = "/tmp/lwidentity.join.log"; BOOLEAN bNoLog = FALSE; PSTR logLevel = "warning"; DWORD dwLogLevel; BOOLEAN showHelp = FALSE; BOOLEAN showInternalHelp = FALSE; BOOLEAN bEnableDcerpcd = TRUE; int remainingArgs = argc; char **argPos = argv; int i; if(!CENTERROR_IS_OK(CTGetTerminalWidth(fileno(stdout), &columns))) columns = -1; /* Skip the program name */ argPos++; remainingArgs--; setlocale(LC_ALL, ""); while(remainingArgs > 0 && CTStrStartsWith(argPos[0], "--")) { if(!strcmp(argPos[0], "--help")) showHelp = TRUE; else if(!strcmp(argPos[0], "--help-internal")) showInternalHelp = TRUE; else if(!strcmp(argPos[0], "--nolog")) bNoLog = TRUE; //All options after this point take an argument else if(remainingArgs < 2) showHelp = TRUE; else if(!strcmp(argPos[0], "--log")) { pszLogFilePath = (++argPos)[0]; remainingArgs--; } else if(!strcmp(argPos[0], "--loglevel")) { logLevel = (++argPos)[0]; remainingArgs--; } else if (!strcmp(argPos[0], "--nodcerpcd")) bEnableDcerpcd = FALSE; else break; remainingArgs--; argPos++; } if(remainingArgs < 1) showHelp = TRUE; if (showInternalHelp) { ShowUsageInternal(); goto cleanup; } if (showHelp) { ShowUsage(); goto cleanup; } if (!strcasecmp(logLevel, "error")) dwLogLevel = LOG_LEVEL_ERROR; else if (!strcasecmp(logLevel, "warning")) dwLogLevel = LOG_LEVEL_WARNING; else if (!strcasecmp(logLevel, "info")) dwLogLevel = LOG_LEVEL_INFO; else if (!strcasecmp(logLevel, "verbose")) dwLogLevel = LOG_LEVEL_VERBOSE; else { LW_CLEANUP_CTERR(&exc, CENTERROR_DOMAINJOIN_INVALID_LOG_LEVEL); } if (bNoLog) { LW_CLEANUP_CTERR(&exc, dj_disable_logging()); } else if (pszLogFilePath == NULL || !strcmp(pszLogFilePath, ".")) { LW_CLEANUP_CTERR(&exc, dj_init_logging_to_console(dwLogLevel)); } else { CENTERROR ceError = dj_init_logging_to_file(dwLogLevel, pszLogFilePath); if(ceError == CENTERROR_ACCESS_DENIED) { fprintf(stderr, "Warning: insufficient permissions to log to %s. To enable logging, please specify a different filename with --log .\n", pszLogFilePath); ceError = CENTERROR_SUCCESS; LW_CLEANUP_CTERR(&exc, dj_disable_logging()); } LW_CLEANUP_CTERR(&exc, ceError); } if (!strcmp(argPos[0], "join") || !strcmp(argPos[0], "leave")) { DJ_LOG_INFO("Domainjoin invoked with the %s command (remaining arguments will be printed later):", argPos[0]); // Only print up to the 'join' part for (i = 0; i <= argPos - argv; i++) { DJ_LOG_INFO(" [%s]", argv[i]); } } else { DJ_LOG_INFO("Domainjoin invoked with %d arg(s):", argc); for (i = 0; i < argc; i++) { DJ_LOG_INFO(" [%s]", argv[i]); } } if(!strcmp(argPos[0], "setname")) { argPos++; if(--remainingArgs != 1) { ShowUsage(); goto cleanup; } //Needed so that DJGetMachineSid does not call winbind LW_TRY(&exc, DJNetInitialize(bEnableDcerpcd, &LW_EXC)); LW_TRY(&exc, DJSetComputerName(argPos[0], NULL, &LW_EXC)); } #ifndef ENABLE_MINIMAL else if(!strcmp(argPos[0], "sync_time")) { unsigned int allowedDrift; argPos++; if(--remainingArgs != 2) { ShowUsage(); goto cleanup; } LW_CLEANUP_CTERR(&exc, ParseUInt(argPos[1], &allowedDrift)); LW_CLEANUP_CTERR(&exc, DJSyncTimeToDC(argPos[0], allowedDrift)); } #endif else if(!strcmp(argPos[0], "join")) { argPos++; remainingArgs--; LW_TRY(&exc, DJNetInitialize(bEnableDcerpcd, &LW_EXC)); LW_TRY(&exc, DoJoin(remainingArgs, argPos, columns, &LW_EXC)); } else if(!strcmp(argPos[0], "leave")) { argPos++; remainingArgs--; LW_TRY(&exc, DJNetInitialize(bEnableDcerpcd, &LW_EXC)); LW_TRY(&exc, DoLeaveNew(remainingArgs, argPos, columns, &LW_EXC)); } else if(!strcmp(argPos[0], "query")) { LW_TRY(&exc, DJNetInitialize(bEnableDcerpcd, &LW_EXC)); LW_TRY(&exc, DoQuery(&LW_EXC)); } else if(!strcmp(argPos[0], "fixfqdn")) LW_TRY(&exc, DoFixFqdn(&LW_EXC)); #ifndef ENABLE_MINIMAL else if(!strcmp(argPos[0], "configure")) { argPos++; remainingArgs--; LW_TRY(&exc, DoConfigure(remainingArgs, argPos, &LW_EXC)); } #endif else if(!strcmp(argPos[0], "get_os_type") || !strcmp(argPos[0], "get_arch") || !strcmp(argPos[0], "get_distro") || !strcmp(argPos[0], "get_distro_version")) { LW_TRY(&exc, DoGetDistroInfo(remainingArgs, argPos, &LW_EXC)); } else if(!strcmp(argPos[0], "raise_error")) { CENTERROR ceError; argPos++; if(--remainingArgs != 1) { ShowUsage(); goto cleanup; } if (isdigit((int) *argPos[0])) ceError = (CENTERROR) strtoul(argPos[0], NULL, 0); else ceError = (CENTERROR) CTErrorFromName(argPos[0]); LW_CLEANUP_CTERR(&exc, ceError); } else { LW_RAISE(&exc, CENTERROR_DOMAINJOIN_SHOW_USAGE); goto cleanup; } cleanup: if (!LW_IS_OK(exc) && exc->code == CENTERROR_DOMAINJOIN_SHOW_USAGE) { ShowUsage(); LWHandle(&exc); } else if (!LW_IS_OK(exc)) { //Ignoring the return value from this because we can't do anything //if there is an error fprintf(stdout, "\n"); LWPrintException(stdout, exc, FALSE); DJLogException(LOG_LEVEL_ERROR, exc); LWHandle(&exc); dj_close_log(); return 1; } DJNetShutdown(NULL); dj_close_log(); return 0; }