/* Fetches the user's credentials from the challenge. * Returns NULL if domain or user is not defined * No identity control is performed. * WARNING! The result is static storage, shared with ntlm_check_auth */ char * fetch_credentials(ntlm_authenticate * auth, int auth_length) { char *p = credentials; lstring tmp; tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->domain); if (tmp.str == NULL) return NULL; memcpy(p, tmp.str, tmp.l); p += tmp.l; *p++ = '\\'; tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->user); if (tmp.str == NULL) return NULL; *(p + tmp.l) = '\0'; return credentials; }
void do_authenticate(ntlm_authenticate * auth, int auth_length) { lstring tmp; int tocopy; NSS_STATUS winbindd_result; struct winbindd_request request; struct winbindd_response response; char *domain, *user; memset(&request, 0, sizeof(struct winbindd_request)); memset(&response, 0, sizeof(struct winbindd_response)); /* domain */ tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->domain); if (tmp.str == NULL || tmp.l == 0) { /* no domain supplied */ request.data.auth_crap.domain[0] = 0; } else { tocopy = min(tmp.l + 1, sizeof(fstring)); xstrncpy(request.data.auth_crap.domain, tmp.str, tocopy); } domain = request.data.auth_crap.domain; /* just a shortcut */ /* username */ tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->user); if (tmp.str == NULL || tmp.l == 0) { authfail(domain, "-", "No username in request"); return; } tocopy = min(sizeof(fstring), tmp.l + 1); xstrncpy(request.data.auth_crap.user, tmp.str, tocopy); user = request.data.auth_crap.user; /* now the LM hash */ lmhash = ntlm_fetch_string((char *) auth, auth_length, &auth->lmresponse); switch (lmhash.l) { case 0: warn("No lm hash provided by user %s\\%s\n", domain, user); request.data.auth_crap.lm_resp_len = 0; break; case 24: memcpy(request.data.auth_crap.lm_resp, lmhash.str, 24); request.data.auth_crap.lm_resp_len = 24; break; default: authfail(domain, user, "Broken LM hash response"); return; } nthash = ntlm_fetch_string((char *) auth, auth_length, &auth->ntresponse); switch (nthash.l) { case 0: debug("no nthash\n"); request.data.auth_crap.nt_resp_len = 0; break; case 24: memcpy(request.data.auth_crap.nt_resp, nthash.str, 24); request.data.auth_crap.nt_resp_len = 24; break; default: debug("nthash len = %d\n", nthash.l); authfail(domain, user, "Broken NT hash response"); return; } debug("Checking user '%s\\%s' lmhash len =%d, have_nthash=%d, " "nthash len=%d\n", domain, user, lmhash.l, have_nthash, nthash.l); memcpy(request.data.auth_crap.chal, challenge, CHALLENGE_LEN); winbindd_result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); debug("winbindd result: %d\n", winbindd_result); if (winbindd_result == NSS_STATUS_SUCCESS) { lc(domain); lc(user); authok(domain, user); } else { char error_buf[200]; snprintf(error_buf, sizeof(error_buf), "Authentication Failure (%s)", response.data.auth.error_string); authfail(domain, user, error_buf); } return; /* useless */ }
/* returns NULL on failure, or a pointer to * the user's credentials (domain\\username) * upon success. WARNING. It's pointing to static storage. * In case of problem sets as side-effect ntlm_errno to one of the * codes defined in ntlm.h */ char * ntlm_check_auth(ntlm_authenticate * auth, int auth_length) { int rv; char pass[MAX_PASSWD_LEN+1]; char *domain = credentials; char *user; lstring tmp; if (handle == NULL) { /*if null we aren't connected, but it shouldn't happen */ debug("Weird, we've been disconnected\n"); ntlm_errno = NTLM_NOT_CONNECTED; return NULL; } /* debug("fetching domain\n"); */ tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->domain); if (tmp.str == NULL || tmp.l == 0) { debug("No domain supplied. Returning no-auth\n"); ntlm_errno = NTLM_LOGON_ERROR; return NULL; } if (tmp.l > MAX_DOMAIN_LEN) { debug("Domain string exceeds %d bytes, rejecting\n", MAX_DOMAIN_LEN); ntlm_errno = NTLM_LOGON_ERROR; return NULL; } memcpy(domain, tmp.str, tmp.l); user = domain + tmp.l; *user++ = '\0'; /* debug("fetching user name\n"); */ tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->user); if (tmp.str == NULL || tmp.l == 0) { debug("No username supplied. Returning no-auth\n"); ntlm_errno = NTLM_LOGON_ERROR; return NULL; } if (tmp.l > MAX_USERNAME_LEN) { debug("Username string exceeds %d bytes, rejecting\n", MAX_USERNAME_LEN); ntlm_errno = NTLM_LOGON_ERROR; return NULL; } memcpy(user, tmp.str, tmp.l); *(user + tmp.l) = '\0'; /* Authenticating against the NT response doesn't seem to work... */ tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->lmresponse); if (tmp.str == NULL || tmp.l == 0) { fprintf(stderr, "No auth at all. Returning no-auth\n"); ntlm_errno = NTLM_LOGON_ERROR; return NULL; } if (tmp.l > MAX_PASSWD_LEN) { debug("Password string exceeds %d bytes, rejecting\n", MAX_PASSWD_LEN); ntlm_errno = NTLM_LOGON_ERROR; return NULL; } memcpy(pass, tmp.str, tmp.l); pass[min(MAX_PASSWD_LEN,tmp.l)] = '\0'; #if 1 debug ("Empty LM pass detection: user: '******', ours:'%s', his: '%s'" "(length: %d)\n", user,lmencoded_empty_pass,tmp.str,tmp.l); if (memcmp(tmp.str,lmencoded_empty_pass,ENCODED_PASS_LEN)==0) { fprintf(stderr,"Empty LM password supplied for user %s\\%s. " "No-auth\n",domain,user); ntlm_errno=NTLM_LOGON_ERROR; return NULL; } tmp = ntlm_fetch_string ((char *) auth, auth_length, &auth->ntresponse); if (tmp.str != NULL && tmp.l != 0) { debug ("Empty NT pass detection: user: '******', ours:'%s', his: '%s'" "(length: %d)\n", user,ntencoded_empty_pass,tmp.str,tmp.l); if (memcmp(tmp.str,lmencoded_empty_pass,ENCODED_PASS_LEN)==0) { fprintf(stderr,"Empty NT password supplied for user %s\\%s. " "No-auth\n",domain,user); ntlm_errno=NTLM_LOGON_ERROR; return NULL; } } #endif /* TODO: check against empty password!!!!! */ debug("checking domain: '%s', user: '******', pass='******'\n", domain, user, pass); rv = SMB_Logon_Server(handle, user, pass, domain, 1); debug("Login attempt had result %d\n", rv); if (rv != NTV_NO_ERROR) { /* failed */ ntlm_errno = rv; return NULL; } *(user - 1) = '\\'; /* hack. Performing, but ugly. */ debug("credentials: %s\n", credentials); return credentials; }