static bool test_wbc_authenticate_user_int(struct torture_context *tctx, const char *correct_password) { struct wbcAuthUserParams params; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *error = NULL; wbcErr ret; ret = wbcAuthenticateUser(cli_credentials_get_username(cmdline_credentials), correct_password); torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS, "wbcAuthenticateUser of %s failed", cli_credentials_get_username(cmdline_credentials)); ZERO_STRUCT(params); params.account_name = cli_credentials_get_username(cmdline_credentials); params.level = WBC_AUTH_USER_LEVEL_PLAIN; params.password.plaintext = correct_password; ret = wbcAuthenticateUserEx(¶ms, &info, &error); torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS, "wbcAuthenticateUserEx of %s failed", params.account_name); wbcFreeMemory(info); info = NULL; wbcFreeMemory(error); error = NULL; params.password.plaintext = "wrong"; ret = wbcAuthenticateUserEx(¶ms, &info, &error); torture_assert_wbc_equal(tctx, ret, WBC_ERR_AUTH_ERROR, "wbcAuthenticateUserEx for %s succeeded where it " "should have failed", params.account_name); wbcFreeMemory(info); info = NULL; wbcFreeMemory(error); error = NULL; return true; }
/* Authenticate a username/password pair */ wbcErr wbcAuthenticateUser(const char *username, const char *password) { wbcErr wbc_status = WBC_ERR_SUCCESS; struct wbcAuthUserParams params; ZERO_STRUCT(params); params.account_name = username; params.level = WBC_AUTH_USER_LEVEL_PLAIN; params.password.plaintext = password; wbc_status = wbcAuthenticateUserEx(¶ms, NULL, NULL); BAIL_ON_WBC_ERROR(wbc_status); done: return wbc_status; }
static bool wbinfo_auth_crap(char *username, const char *pass) { wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; struct wbcAuthUserParams params; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *err = NULL; DATA_BLOB lm = data_blob_null; DATA_BLOB nt = data_blob_null; fstring name_user; fstring name_domain; parse_wbinfo_domain_user(username, name_domain, name_user); params.account_name = name_user; params.domain_name = name_domain; params.workstation_name = NULL; params.flags = 0; params.parameter_control= WBC_MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | WBC_MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT; params.level = WBC_AUTH_USER_LEVEL_RESPONSE; generate_random_buffer(params.password.response.challenge, 8); if (lp_client_ntlmv2_auth()) { DATA_BLOB server_chal; DATA_BLOB names_blob; server_chal = data_blob(params.password.response.challenge, 8); /* Pretend this is a login to 'us', for blob purposes */ names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup()); if (!SMBNTLMv2encrypt(name_user, name_domain, pass, &server_chal, &names_blob, &lm, &nt, NULL)) { data_blob_free(&names_blob); data_blob_free(&server_chal); return false; } data_blob_free(&names_blob); data_blob_free(&server_chal); } else { if (lp_client_lanman_auth()) { bool ok; lm = data_blob(NULL, 24); ok = SMBencrypt(pass, params.password.response.challenge, lm.data); if (!ok) { data_blob_free(&lm); } } nt = data_blob(NULL, 24); SMBNTencrypt(pass, params.password.response.challenge, nt.data); } params.password.response.nt_length = nt.length; params.password.response.nt_data = nt.data; params.password.response.lm_length = lm.length; params.password.response.lm_data = lm.data; wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); /* Display response */ d_printf("challenge/response password authentication %s\n", WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed"); if (wbc_status == WBC_ERR_AUTH_ERROR) { d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", err->nt_string, err->nt_status, err->display_string); wbcFreeMemory(err); } else if (WBC_ERROR_IS_OK(wbc_status)) { wbcFreeMemory(info); } data_blob_free(&nt); data_blob_free(&lm); return WBC_ERROR_IS_OK(wbc_status); }
static NTSTATUS check_wbc_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; wbcErr wbc_status; struct wbcAuthUserParams params; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *err = NULL; if (!user_info || !auth_context || !server_info) { return NT_STATUS_INVALID_PARAMETER; } /* Send off request */ params.account_name = user_info->smb_name; params.domain_name = user_info->domain; params.workstation_name = user_info->wksta_name; params.flags = 0; params.parameter_control= user_info->logon_parameters; /* Handle plaintext */ if (!user_info->encrypted) { DEBUG(3,("Checking plaintext password for %s.\n", user_info->internal_username)); params.level = WBC_AUTH_USER_LEVEL_PLAIN; params.password.plaintext = (char *)user_info->plaintext_password.data; } else { DEBUG(3,("Checking encrypted password for %s.\n", user_info->internal_username)); params.level = WBC_AUTH_USER_LEVEL_RESPONSE; memcpy(params.password.response.challenge, auth_context->challenge.data, sizeof(params.password.response.challenge)); params.password.response.nt_length = user_info->nt_resp.length; params.password.response.nt_data = user_info->nt_resp.data; params.password.response.lm_length = user_info->lm_resp.length; params.password.response.lm_data = user_info->lm_resp.data; } /* we are contacting the privileged pipe */ become_root(); wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); unbecome_root(); if (!WBC_ERROR_IS_OK(wbc_status)) { DEBUG(10,("wbcAuthenticateUserEx failed (%d): %s\n", wbc_status, wbcErrorString(wbc_status))); } if (wbc_status == WBC_ERR_NO_MEMORY) { return NT_STATUS_NO_MEMORY; } if (wbc_status == WBC_ERR_AUTH_ERROR) { nt_status = NT_STATUS(err->nt_status); wbcFreeMemory(err); return nt_status; } if (!WBC_ERROR_IS_OK(wbc_status)) { return NT_STATUS_LOGON_FAILURE; } DEBUG(10,("wbcAuthenticateUserEx succeeded\n")); nt_status = make_server_info_wbcAuthUserInfo(mem_ctx, user_info->smb_name, user_info->domain, info, server_info); wbcFreeMemory(info); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } (*server_info)->nss_token |= user_info->was_mapped; return nt_status; }
static NTSTATUS check_winbind_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; wbcErr wbc_status; struct wbcAuthUserParams params; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *err = NULL; ZERO_STRUCT(params); if (!user_info) { return NT_STATUS_INVALID_PARAMETER; } DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name)); if (!auth_context) { DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", user_info->mapped.account_name)); return NT_STATUS_INVALID_PARAMETER; } if (strequal(user_info->mapped.domain_name, get_global_sam_name())) { DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n", user_info->mapped.domain_name)); return NT_STATUS_NOT_IMPLEMENTED; } /* Send off request */ params.account_name = user_info->client.account_name; /* * We need to send the domain name from the client to the DC. With * NTLMv2 the domain name is part of the hashed second challenge, * if we change the domain name, the DC will fail to verify the * challenge cause we changed the domain name, this is like a * man in the middle attack. */ params.domain_name = user_info->client.domain_name; params.workstation_name = user_info->workstation_name; params.flags = 0; params.parameter_control= user_info->logon_parameters; params.level = WBC_AUTH_USER_LEVEL_RESPONSE; memcpy(params.password.response.challenge, auth_context->challenge.data, sizeof(params.password.response.challenge)); if (user_info->password.response.nt.length != 0) { params.password.response.nt_length = user_info->password.response.nt.length; params.password.response.nt_data = user_info->password.response.nt.data; } if (user_info->password.response.lanman.length != 0) { params.password.response.lm_length = user_info->password.response.lanman.length; params.password.response.lm_data = user_info->password.response.lanman.data; } /* we are contacting the privileged pipe */ become_root(); wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); unbecome_root(); if (!WBC_ERROR_IS_OK(wbc_status)) { DEBUG(10,("check_winbind_security: wbcAuthenticateUserEx failed: %s\n", wbcErrorString(wbc_status))); } if (wbc_status == WBC_ERR_NO_MEMORY) { return NT_STATUS_NO_MEMORY; } if (wbc_status == WBC_ERR_WINBIND_NOT_AVAILABLE) { struct auth_methods *auth_method = (struct auth_methods *)my_private_data; if ( auth_method ) return auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); return NT_STATUS_LOGON_FAILURE; } if (wbc_status == WBC_ERR_AUTH_ERROR) { nt_status = NT_STATUS(err->nt_status); wbcFreeMemory(err); return nt_status; } if (!WBC_ERROR_IS_OK(wbc_status)) { return NT_STATUS_LOGON_FAILURE; } nt_status = make_server_info_wbcAuthUserInfo(mem_ctx, user_info->client.account_name, user_info->mapped.domain_name, info, server_info); wbcFreeMemory(info); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } (*server_info)->nss_token |= user_info->was_mapped; return nt_status; }
/** * @brief Convert a principal (as returned by @c gss_display_name) to a UID * * @param[in] name The principal of the user * @param[out] uid The resulting UID * * @return true if successful, false otherwise */ bool principal2uid(char *principal, uid_t *uid, gid_t *gid) #endif { #ifdef USE_NFSIDMAP uid_t gss_uid = ANON_UID; gid_t gss_gid = ANON_GID; const gid_t *gss_gidres = NULL; int rc; bool success; struct gsh_buffdesc princbuff = { .addr = principal, .len = strlen(principal) }; #endif if (nfs_param.nfsv4_param.use_getpwnam) return false; #ifdef USE_NFSIDMAP PTHREAD_RWLOCK_rdlock(&idmapper_user_lock); success = idmapper_lookup_by_uname(&princbuff, &gss_uid, &gss_gidres, true); if (success && gss_gidres) gss_gid = *gss_gidres; PTHREAD_RWLOCK_unlock(&idmapper_user_lock); if (unlikely(!success)) { if ((princbuff.len >= 4) && (!memcmp(princbuff.addr, "nfs/", 4) || !memcmp(princbuff.addr, "root/", 5) || !memcmp(princbuff.addr, "host/", 5))) { /* NFSv4 specific features: RPCSEC_GSS will * provide user like * * nfs/<host> * root/<host> * host/<host> * choice is made to map them to root */ /* This is a "root" request made from the hostbased nfs principal, use root */ *uid = 0; return true; } /* nfs4_gss_princ_to_ids required to extract uid/gid from gss creds */ rc = nfs4_gss_princ_to_ids("krb5", principal, &gss_uid, &gss_gid); if (rc) { #ifdef _MSPAC_SUPPORT bool found_uid = false; bool found_gid = false; if (gd->flags & SVC_RPC_GSS_FLAG_MSPAC) { struct wbcAuthUserParams params; wbcErr wbc_err; struct wbcAuthUserInfo *info; struct wbcAuthErrorInfo *error = NULL; memset(¶ms, 0, sizeof(params)); params.level = WBC_AUTH_USER_LEVEL_PAC; params.password.pac.data = (uint8_t *) gd->pac.ms_pac.value; params.password.pac.length = gd->pac.ms_pac.length; wbc_err = wbcAuthenticateUserEx(¶ms, &info, &error); if (!WBC_ERROR_IS_OK(wbc_err)) { LogCrit(COMPONENT_IDMAPPER, "wbcAuthenticateUserEx returned %s", wbcErrorString(wbc_err)); return false; } if (error) { LogCrit(COMPONENT_IDMAPPER, "nt_status: %s, display_string %s", error->nt_string, error->display_string); wbcFreeMemory(error); return false; } /* 1st SID is account sid, see wbclient.h */ wbc_err = wbcSidToUid(&info->sids[0].sid, &gss_uid); if (!WBC_ERROR_IS_OK(wbc_err)) { LogCrit(COMPONENT_IDMAPPER, "wbcSidToUid for uid returned %s", wbcErrorString(wbc_err)); wbcFreeMemory(info); return false; } /* 2nd SID is primary_group sid, see wbclient.h */ wbc_err = wbcSidToGid(&info->sids[1].sid, &gss_gid); if (!WBC_ERROR_IS_OK(wbc_err)) { LogCrit(COMPONENT_IDMAPPER, "wbcSidToUid for gid returned %s\n", wbcErrorString(wbc_err)); wbcFreeMemory(info); return false; } wbcFreeMemory(info); found_uid = true; found_gid = true; } #endif /* _MSPAC_SUPPORT */ #ifdef _MSPAC_SUPPORT if ((found_uid == true) && (found_gid == true)) goto principal_found; #endif return false; } #ifdef _MSPAC_SUPPORT principal_found: #endif PTHREAD_RWLOCK_wrlock(&idmapper_user_lock); success = idmapper_add_user(&princbuff, gss_uid, &gss_gid, true); PTHREAD_RWLOCK_unlock(&idmapper_user_lock); if (!success) { LogMajor(COMPONENT_IDMAPPER, "idmapper_add_user(%s, %d, %d) failed", principal, gss_uid, gss_gid); } } *uid = gss_uid; *gid = gss_gid; return true; #else /* !USE_NFSIDMAP */ assert(!"prohibited by configuration"); return false; #endif }
static NTSTATUS check_winbind_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status; wbcErr wbc_status; struct wbcAuthUserParams params; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *err = NULL; if (!user_info) { return NT_STATUS_INVALID_PARAMETER; } if (!auth_context) { DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", user_info->internal_username)); return NT_STATUS_INVALID_PARAMETER; } if (strequal(user_info->domain, get_global_sam_name())) { DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n", user_info->domain)); return NT_STATUS_NOT_IMPLEMENTED; } /* Send off request */ params.account_name = user_info->smb_name; params.domain_name = user_info->domain; params.workstation_name = user_info->wksta_name; params.flags = 0; params.parameter_control= user_info->logon_parameters; params.level = WBC_AUTH_USER_LEVEL_RESPONSE; memcpy(params.password.response.challenge, auth_context->challenge.data, sizeof(params.password.response.challenge)); params.password.response.nt_length = user_info->nt_resp.length; params.password.response.nt_data = user_info->nt_resp.data; params.password.response.lm_length = user_info->lm_resp.length; params.password.response.lm_data = user_info->lm_resp.data; /* we are contacting the privileged pipe */ become_root(); wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); unbecome_root(); if (!WBC_ERROR_IS_OK(wbc_status)) { DEBUG(10,("check_winbind_security: wbcAuthenticateUserEx failed: %s\n", wbcErrorString(wbc_status))); } if (wbc_status == WBC_ERR_NO_MEMORY) { return NT_STATUS_NO_MEMORY; } if (wbc_status == WBC_ERR_WINBIND_NOT_AVAILABLE) { struct auth_methods *auth_method = (struct auth_methods *)my_private_data; if ( auth_method ) return auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); else /* log an error since this should not happen */ DEBUG(0,("check_winbind_security: ERROR! my_private_data == NULL!\n")); } if (wbc_status == WBC_ERR_AUTH_ERROR) { nt_status = NT_STATUS(err->nt_status); wbcFreeMemory(err); return nt_status; } if (!WBC_ERROR_IS_OK(wbc_status)) { return NT_STATUS_LOGON_FAILURE; } nt_status = make_server_info_wbcAuthUserInfo(mem_ctx, user_info->smb_name, user_info->domain, info, server_info); wbcFreeMemory(info); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } (*server_info)->nss_token |= user_info->was_mapped; return nt_status; }