static bool print_domain_groups(const char *domain) { wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; uint32_t i; uint32_t num_groups = 0; const char **groups = NULL; /* Send request to winbind daemon */ /* '.' is the special sign for our own domain */ if (domain && strcmp(domain, ".") == 0) { domain = get_winbind_domain(); } wbc_status = wbcListGroups(domain, &num_groups, &groups); if (!WBC_ERROR_IS_OK(wbc_status)) { return false; } for (i=0; i < num_groups; i++) { d_printf("%s\n", groups[i]); } wbcFreeMemory(groups); return true; }
int main(int argc, char **argv) { char *target_domain; if (argc > 0) { /* should always be true */ myname = strrchr(argv[0], '/'); if (myname == NULL) myname = argv[0]; else myname++; } else { myname = "(unknown)"; } mypid = getpid(); target_domain = process_options(argc, argv); debug("ntlm winbindd auth helper build " __DATE__ ", " __TIME__ " starting up...\n"); check_winbindd(); if (target_domain == NULL) { target_domain = get_winbind_domain(); } /* initialize FDescs */ setbuf(stdout, NULL); setbuf(stderr, NULL); init_random(); while (manage_request(target_domain)) { /* everything is done within manage_request */ } return 0; }
static bool parse_wbinfo_domain_user(const char *domuser, fstring domain, fstring user) { char *p = strchr(domuser,winbind_separator()); if (!p) { /* Maybe it was a UPN? */ if ((p = strchr(domuser, '@')) != NULL) { fstrcpy(domain, ""); fstrcpy(user, domuser); return true; } fstrcpy(user, domuser); fstrcpy(domain, get_winbind_domain()); return true; } fstrcpy(user, p+1); fstrcpy(domain, domuser); domain[PTR_DIFF(p, domuser)] = 0; strupper_m(domain); return true; }
static bool print_domain_groups(const char *domain) { struct winbindd_request request; struct winbindd_response response; const char *extra_data; fstring name; ZERO_STRUCT(request); ZERO_STRUCT(response); if (domain) { if ( strequal(domain, ".") ) fstrcpy( request.domain_name, get_winbind_domain() ); else fstrcpy( request.domain_name, domain ); } if (winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response) != NSS_STATUS_SUCCESS) return false; /* Look through extra data */ if (!response.extra_data.data) return false; extra_data = (const char *)response.extra_data.data; while(next_token(&extra_data, name, ",", sizeof(fstring))) d_printf("%s\n", name); SAFE_FREE(response.extra_data.data); return true; }
static bool wbinfo_get_sidaliases(const char *domain, const char *user_sid_str) { wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; struct wbcDomainInfo *dinfo = NULL; uint32_t i; struct wbcDomainSid user_sid; uint32_t *alias_rids = NULL; uint32_t num_alias_rids; char *domain_sid_str = NULL; /* Send request */ if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')) { domain = get_winbind_domain(); } /* Send request */ wbc_status = wbcDomainInfo(domain, &dinfo); if (!WBC_ERROR_IS_OK(wbc_status)) { d_printf("wbcDomainInfo(%s) failed: %s\n", domain, wbcErrorString(wbc_status)); goto done; } wbc_status = wbcStringToSid(user_sid_str, &user_sid); if (!WBC_ERROR_IS_OK(wbc_status)) { goto done; } wbc_status = wbcGetSidAliases(&dinfo->sid, &user_sid, 1, &alias_rids, &num_alias_rids); if (!WBC_ERROR_IS_OK(wbc_status)) { goto done; } wbc_status = wbcSidToString(&dinfo->sid, &domain_sid_str); if (!WBC_ERROR_IS_OK(wbc_status)) { goto done; } for (i = 0; i < num_alias_rids; i++) { d_printf("%s-%d\n", domain_sid_str, alias_rids[i]); } wbcFreeMemory(alias_rids); done: if (domain_sid_str) { wbcFreeMemory(domain_sid_str); } if (dinfo) { wbcFreeMemory(dinfo); } return (WBC_ERR_SUCCESS == wbc_status); }
static bool torture_winbind_struct_domain_name(struct torture_context *torture) { const char *expected; char *domain; torture_comment(torture, "Running WINBINDD_DOMAIN_NAME (struct based)\n"); expected = torture_setting_string(torture, "winbindd_netbios_domain", lpcfg_workgroup(torture->lp_ctx)); get_winbind_domain(torture, &domain); torture_assert_str_equal(torture, domain, expected, "winbindd's netbios domain doesn't match"); return true; }
static bool wbinfo_domain_info(const char *domain) { wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; struct wbcDomainInfo *dinfo = NULL; char *sid_str = NULL; if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')) { domain = get_winbind_domain(); } /* Send request */ wbc_status = wbcDomainInfo(domain, &dinfo); if (!WBC_ERROR_IS_OK(wbc_status)) { return false; } wbc_status = wbcSidToString(&dinfo->sid, &sid_str); if (!WBC_ERROR_IS_OK(wbc_status)) { wbcFreeMemory(dinfo); return false; } /* Display response */ d_printf("Name : %s\n", dinfo->short_name); d_printf("Alt_Name : %s\n", dinfo->dns_name); d_printf("SID : %s\n", sid_str); d_printf("Active Directory : %s\n", (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_AD) ? "Yes" : "No"); d_printf("Native : %s\n", (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_NATIVE) ? "Yes" : "No"); d_printf("Primary : %s\n", (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_PRIMARY) ? "Yes" : "No"); wbcFreeMemory(sid_str); wbcFreeMemory(dinfo); return true; }
static bool wbinfo_domain_info(const char *domain_name) { struct winbindd_request request; struct winbindd_response response; ZERO_STRUCT(request); ZERO_STRUCT(response); if ((strequal(domain_name, ".")) || (domain_name[0] == '\0')) fstrcpy(request.domain_name, get_winbind_domain()); else fstrcpy(request.domain_name, domain_name); /* Send request */ if (winbindd_request_response(WINBINDD_DOMAIN_INFO, &request, &response) != NSS_STATUS_SUCCESS) return false; /* Display response */ d_printf("Name : %s\n", response.data.domain_info.name); d_printf("Alt_Name : %s\n", response.data.domain_info.alt_name); d_printf("SID : %s\n", response.data.domain_info.sid); d_printf("Active Directory : %s\n", response.data.domain_info.active_directory ? "Yes" : "No"); d_printf("Native : %s\n", response.data.domain_info.native_mode ? "Yes" : "No"); d_printf("Primary : %s\n", response.data.domain_info.primary ? "Yes" : "No"); return true; }
static bool wbinfo_lookuprids(const char *domain, const char *arg) { wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; struct wbcDomainInfo *dinfo = NULL; char *domain_name = NULL; const char **names = NULL; enum wbcSidType *types = NULL; size_t i; int num_rids; uint32 *rids = NULL; const char *p; char *ridstr; TALLOC_CTX *mem_ctx = NULL; bool ret = false; if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')) { domain = get_winbind_domain(); } /* Send request */ wbc_status = wbcDomainInfo(domain, &dinfo); if (!WBC_ERROR_IS_OK(wbc_status)) { d_printf("wbcDomainInfo(%s) failed: %s\n", domain, wbcErrorString(wbc_status)); goto done; } mem_ctx = talloc_new(NULL); if (mem_ctx == NULL) { d_printf("talloc_new failed\n"); goto done; } num_rids = 0; rids = NULL; p = arg; while (next_token_talloc(mem_ctx, &p, &ridstr, " ,\n")) { uint32 rid = strtoul(ridstr, NULL, 10); ADD_TO_ARRAY(mem_ctx, uint32, rid, &rids, &num_rids); } if (rids == NULL) { d_printf("no rids\n"); goto done; } wbc_status = wbcLookupRids(&dinfo->sid, num_rids, rids, (const char **)&domain_name, &names, &types); if (!WBC_ERROR_IS_OK(wbc_status)) { d_printf("winbind_lookup_rids failed: %s\n", wbcErrorString(wbc_status)); goto done; } d_printf("Domain: %s\n", domain_name); for (i=0; i<num_rids; i++) { d_printf("%8d: %s (%s)\n", rids[i], names[i], sid_type_lookup(types[i])); } ret = true; done: if (dinfo) { wbcFreeMemory(dinfo); } if (domain_name) { wbcFreeMemory(domain_name); } if (names) { wbcFreeMemory(names); } if (types) { wbcFreeMemory(types); } TALLOC_FREE(mem_ctx); return ret; }
static bool wbinfo_list_own_domain(void) { d_printf("%s\n", get_winbind_domain()); return true; }
static bool test_lmv2_ntlmv2_broken(enum ntlm_break break_which) { bool pass = True; NTSTATUS nt_status; uint32 flags = 0; DATA_BLOB ntlmv2_response = data_blob_null; DATA_BLOB lmv2_response = data_blob_null; DATA_BLOB ntlmv2_session_key = data_blob_null; DATA_BLOB names_blob = NTLMv2_generate_names_blob(NULL, get_winbind_netbios_name(), get_winbind_domain()); uchar user_session_key[16]; DATA_BLOB chall = get_challenge(); char *error_string; ZERO_STRUCT(user_session_key); flags |= WBFLAG_PAM_USER_SESSION_KEY; if (!SMBNTLMv2encrypt(NULL, opt_username, opt_domain, opt_password, &chall, &names_blob, &lmv2_response, &ntlmv2_response, NULL, &ntlmv2_session_key)) { data_blob_free(&names_blob); return False; } data_blob_free(&names_blob); switch (break_which) { case BREAK_NONE: break; case BREAK_LM: lmv2_response.data[0]++; break; case BREAK_NT: ntlmv2_response.data[0]++; break; case NO_LM: data_blob_free(&lmv2_response); break; case NO_NT: data_blob_free(&ntlmv2_response); break; } nt_status = contact_winbind_auth_crap(opt_username, opt_domain, opt_workstation, &chall, &lmv2_response, &ntlmv2_response, flags, NULL, user_session_key, &error_string, NULL); data_blob_free(&lmv2_response); data_blob_free(&ntlmv2_response); if (!NT_STATUS_IS_OK(nt_status)) { d_printf("%s (0x%x)\n", error_string, NT_STATUS_V(nt_status)); SAFE_FREE(error_string); return break_which == BREAK_NT; } if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key, sizeof(user_session_key)) != 0) { DEBUG(1, ("USER (NTLMv2) Session Key does not match expectations!\n")); DEBUG(1, ("user_session_key:\n")); dump_data(1, user_session_key, 16); DEBUG(1, ("expected:\n")); dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length); pass = False; } return pass; }
int main(int argc, const char **argv) { int opt; static const char *helper_protocol; static int diagnostics; static const char *hex_challenge; static const char *hex_lm_response; static const char *hex_nt_response; poptContext pc; /* NOTE: DO NOT change this interface without considering the implications! This is an external interface, which other programs will use to interact with this helper. */ /* We do not use single-letter command abbreviations, because they harm future interface stability. */ struct poptOption long_options[] = { POPT_AUTOHELP { "helper-protocol", 0, POPT_ARG_STRING, &helper_protocol, OPT_DOMAIN, "operate as a stdio-based helper", "helper protocol to use"}, { "username", 0, POPT_ARG_STRING, &opt_username, OPT_USERNAME, "username"}, { "domain", 0, POPT_ARG_STRING, &opt_domain, OPT_DOMAIN, "domain name"}, { "workstation", 0, POPT_ARG_STRING, &opt_workstation, OPT_WORKSTATION, "workstation"}, { "challenge", 0, POPT_ARG_STRING, &hex_challenge, OPT_CHALLENGE, "challenge (HEX encoded)"}, { "lm-response", 0, POPT_ARG_STRING, &hex_lm_response, OPT_LM, "LM Response to the challenge (HEX encoded)"}, { "nt-response", 0, POPT_ARG_STRING, &hex_nt_response, OPT_NT, "NT or NTLMv2 Response to the challenge (HEX encoded)"}, { "password", 0, POPT_ARG_STRING, &opt_password, OPT_PASSWORD, "User's plaintext password"}, { "request-lm-key", 0, POPT_ARG_NONE, &request_lm_key, OPT_LM_KEY, "Retrieve LM session key"}, { "request-nt-key", 0, POPT_ARG_NONE, &request_user_session_key, OPT_USER_SESSION_KEY, "Retrieve User (NT) session key"}, { "diagnostics", 0, POPT_ARG_NONE, &diagnostics, OPT_DIAGNOSTICS, "Perform diagnostics on the authentictaion chain"}, { "require-membership-of", 0, POPT_ARG_STRING, &require_membership_of, OPT_REQUIRE_MEMBERSHIP, "Require that a user be a member of this group (either name or SID) for authentication to succeed" }, POPT_COMMON_SAMBA POPT_TABLEEND }; /* Samba client initialisation */ load_case_tables(); dbf = x_stderr; /* Samba client initialisation */ if (!lp_load(dyn_CONFIGFILE, True, False, False, True)) { d_fprintf(stderr, "ntlm_auth: error opening config file %s. Error was %s\n", dyn_CONFIGFILE, strerror(errno)); exit(1); } /* Parse options */ pc = poptGetContext("ntlm_auth", argc, argv, long_options, 0); /* Parse command line options */ if (argc == 1) { poptPrintHelp(pc, stderr, 0); return 1; } pc = poptGetContext(NULL, argc, (const char **)argv, long_options, POPT_CONTEXT_KEEP_FIRST); while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_CHALLENGE: opt_challenge = strhex_to_data_blob(NULL, hex_challenge); if (opt_challenge.length != 8) { x_fprintf(x_stderr, "hex decode of %s failed! (only got %d bytes)\n", hex_challenge, (int)opt_challenge.length); exit(1); } break; case OPT_LM: opt_lm_response = strhex_to_data_blob(NULL, hex_lm_response); if (opt_lm_response.length != 24) { x_fprintf(x_stderr, "hex decode of %s failed! (only got %d bytes)\n", hex_lm_response, (int)opt_lm_response.length); exit(1); } break; case OPT_NT: opt_nt_response = strhex_to_data_blob(NULL, hex_nt_response); if (opt_nt_response.length < 24) { x_fprintf(x_stderr, "hex decode of %s failed! (only got %d bytes)\n", hex_nt_response, (int)opt_nt_response.length); exit(1); } break; case OPT_REQUIRE_MEMBERSHIP: if (StrnCaseCmp("S-", require_membership_of, 2) == 0) { require_membership_of_sid = require_membership_of; } break; } } if (opt_username) { char *domain = SMB_STRDUP(opt_username); char *p = strchr_m(domain, *lp_winbind_separator()); if (p) { opt_username = p+1; *p = '\0'; if (opt_domain && !strequal(opt_domain, domain)) { x_fprintf(x_stderr, "Domain specified in username (%s) " "doesn't match specified domain (%s)!\n\n", domain, opt_domain); poptPrintHelp(pc, stderr, 0); exit(1); } opt_domain = domain; } else { SAFE_FREE(domain); } } if (opt_domain == NULL || !*opt_domain) { opt_domain = get_winbind_domain(); } if (opt_workstation == NULL) { opt_workstation = ""; } if (helper_protocol) { int i; for (i=0; i<NUM_HELPER_MODES; i++) { if (strcmp(helper_protocol, stdio_helper_protocols[i].name) == 0) { squid_stream(stdio_helper_protocols[i].mode, stdio_helper_protocols[i].fn); exit(0); } } x_fprintf(x_stderr, "unknown helper protocol [%s]\n\nValid helper protools:\n\n", helper_protocol); for (i=0; i<NUM_HELPER_MODES; i++) { x_fprintf(x_stderr, "%s\n", stdio_helper_protocols[i].name); } exit(1); } if (!opt_username || !*opt_username) { x_fprintf(x_stderr, "username must be specified!\n\n"); poptPrintHelp(pc, stderr, 0); exit(1); } if (opt_challenge.length) { if (!check_auth_crap()) { exit(1); } exit(0); } if (!opt_password) { opt_password = getpass("password: "******"%s%c%s", opt_domain, winbind_separator(), opt_username); if (!check_plaintext_auth(user, opt_password, True)) { return 1; } } /* Exit code */ poptFreeContext(pc); return 0; }
static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mode, char *buf, int length) { char *request, *parameter; static DATA_BLOB challenge; static DATA_BLOB lm_response; static DATA_BLOB nt_response; static char *full_username; static char *username; static char *domain; static char *plaintext_password; static BOOL ntlm_server_1_user_session_key; static BOOL ntlm_server_1_lm_session_key; if (strequal(buf, ".")) { if (!full_username && !username) { x_fprintf(x_stdout, "Error: No username supplied!\n"); } else if (plaintext_password) { /* handle this request as plaintext */ if (!full_username) { if (asprintf(&full_username, "%s%c%s", domain, winbind_separator(), username) == -1) { x_fprintf(x_stdout, "Error: Out of memory in asprintf!\n.\n"); return; } } if (check_plaintext_auth(full_username, plaintext_password, False)) { x_fprintf(x_stdout, "Authenticated: Yes\n"); } else { x_fprintf(x_stdout, "Authenticated: No\n"); } } else if (!lm_response.data && !nt_response.data) { x_fprintf(x_stdout, "Error: No password supplied!\n"); } else if (!challenge.data) { x_fprintf(x_stdout, "Error: No lanman-challenge supplied!\n"); } else { char *error_string = NULL; uchar lm_key[8]; uchar user_session_key[16]; uint32 flags = 0; if (full_username && !username) { fstring fstr_user; fstring fstr_domain; if (!parse_ntlm_auth_domain_user(full_username, fstr_user, fstr_domain)) { /* username might be 'tainted', don't print into our new-line deleimianted stream */ x_fprintf(x_stdout, "Error: Could not parse into domain and username\n"); } SAFE_FREE(username); SAFE_FREE(domain); username = smb_xstrdup(fstr_user); domain = smb_xstrdup(fstr_domain); } if (!domain) { domain = smb_xstrdup(get_winbind_domain()); } if (ntlm_server_1_lm_session_key) flags |= WBFLAG_PAM_LMKEY; if (ntlm_server_1_user_session_key) flags |= WBFLAG_PAM_USER_SESSION_KEY; if (!NT_STATUS_IS_OK( contact_winbind_auth_crap(username, domain, global_myname(), &challenge, &lm_response, &nt_response, flags, lm_key, user_session_key, &error_string, NULL))) { x_fprintf(x_stdout, "Authenticated: No\n"); x_fprintf(x_stdout, "Authentication-Error: %s\n.\n", error_string); SAFE_FREE(error_string); } else { static char zeros[16]; char *hex_lm_key; char *hex_user_session_key; x_fprintf(x_stdout, "Authenticated: Yes\n"); if (ntlm_server_1_lm_session_key && (memcmp(zeros, lm_key, sizeof(lm_key)) != 0)) { hex_lm_key = hex_encode(NULL, (const unsigned char *)lm_key, sizeof(lm_key)); x_fprintf(x_stdout, "LANMAN-Session-Key: %s\n", hex_lm_key); TALLOC_FREE(hex_lm_key); } if (ntlm_server_1_user_session_key && (memcmp(zeros, user_session_key, sizeof(user_session_key)) != 0)) { hex_user_session_key = hex_encode(NULL, (const unsigned char *)user_session_key, sizeof(user_session_key)); x_fprintf(x_stdout, "User-Session-Key: %s\n", hex_user_session_key); TALLOC_FREE(hex_user_session_key); } } } /* clear out the state */ challenge = data_blob(NULL, 0); nt_response = data_blob(NULL, 0); lm_response = data_blob(NULL, 0); SAFE_FREE(full_username); SAFE_FREE(username); SAFE_FREE(domain); SAFE_FREE(plaintext_password); ntlm_server_1_user_session_key = False; ntlm_server_1_lm_session_key = False; x_fprintf(x_stdout, ".\n"); return; } request = buf; /* Indicates a base64 encoded structure */ parameter = strstr_m(request, ":: "); if (!parameter) { parameter = strstr_m(request, ": "); if (!parameter) { DEBUG(0, ("Parameter not found!\n")); x_fprintf(x_stdout, "Error: Parameter not found!\n.\n"); return; } parameter[0] ='\0'; parameter++; parameter[0] ='\0'; parameter++; } else { parameter[0] ='\0'; parameter++; parameter[0] ='\0'; parameter++; parameter[0] ='\0'; parameter++; base64_decode_inplace(parameter); } if (strequal(request, "LANMAN-Challenge")) { challenge = strhex_to_data_blob(NULL, parameter); if (challenge.length != 8) { x_fprintf(x_stdout, "Error: hex decode of %s failed! (got %d bytes, expected 8)\n.\n", parameter, (int)challenge.length); challenge = data_blob(NULL, 0); } } else if (strequal(request, "NT-Response")) { nt_response = strhex_to_data_blob(NULL, parameter); if (nt_response.length < 24) { x_fprintf(x_stdout, "Error: hex decode of %s failed! (only got %d bytes, needed at least 24)\n.\n", parameter, (int)nt_response.length); nt_response = data_blob(NULL, 0); } } else if (strequal(request, "LANMAN-Response")) { lm_response = strhex_to_data_blob(NULL, parameter); if (lm_response.length != 24) { x_fprintf(x_stdout, "Error: hex decode of %s failed! (got %d bytes, expected 24)\n.\n", parameter, (int)lm_response.length); lm_response = data_blob(NULL, 0); } } else if (strequal(request, "Password")) { plaintext_password = smb_xstrdup(parameter); } else if (strequal(request, "NT-Domain")) { domain = smb_xstrdup(parameter); } else if (strequal(request, "Username")) { username = smb_xstrdup(parameter); } else if (strequal(request, "Full-Username")) { full_username = smb_xstrdup(parameter); } else if (strequal(request, "Request-User-Session-Key")) { ntlm_server_1_user_session_key = strequal(parameter, "Yes"); } else if (strequal(request, "Request-LanMan-Session-Key")) { ntlm_server_1_lm_session_key = strequal(parameter, "Yes"); } else { x_fprintf(x_stdout, "Error: Unknown request %s\n.\n", request); } }