JNIEXPORT jboolean JNICALL Java_com_cenqua_shaj_Win32Authenticator_checkGroupMembershipImpl (JNIEnv * jvm, jclass jThisClass, jstring aDomain, jstring aUsername, jstring aGroup, jobject jLog) { const jchar* wc_domain; const jchar* wc_username; const jchar* wc_group; loginfo_t loginfo; jboolean result; HANDLE token = NULL; BOOL status = 1; loginfo = shaj_init_logger(jvm, jLog); wc_domain = (aDomain == NULL) ? NULL : (*jvm)->GetStringChars(jvm, aDomain, NULL); wc_username = (*jvm)->GetStringChars(jvm, aUsername, NULL); wc_group = (*jvm)->GetStringChars(jvm, aGroup, NULL); status = shaj_memberOfGroup(wc_domain, wc_username, wc_group, TRUE, TRUE, TRUE, &loginfo); result = status ? JNI_TRUE : JNI_FALSE; shaj_log_debug(&loginfo, "checking group for domain=%ws user=%ws group=%ws => %d", (wc_domain==NULL)? L"(NULL)" : wc_domain, wc_username, wc_group, (int) result); if (aDomain != NULL) { (*jvm)->ReleaseStringChars(jvm, aDomain, wc_domain); } (*jvm)->ReleaseStringChars(jvm, aUsername, wc_username); (*jvm)->ReleaseStringChars(jvm, aGroup, wc_group); return result; }
JNIEXPORT jboolean JNICALL Java_com_cenqua_shaj_Win32Authenticator_checkPasswordImpl (JNIEnv * jvm, jclass jThisClass, jstring aDomain, jstring aUsername, jstring aPassword, jobject jLog) { const char* c_domain; const char* c_username; const char* c_password; loginfo_t loginfo; jboolean result; HANDLE token = NULL; BOOL status = 1; loginfo = shaj_init_logger(jvm, jLog); c_domain = (aDomain == NULL) ? NULL : (*jvm)->GetStringUTFChars(jvm, aDomain, NULL); c_username = (*jvm)->GetStringUTFChars(jvm, aUsername, NULL); c_password = (*jvm)->GetStringUTFChars(jvm, aPassword, NULL); status = SSPLogonUser((char*)c_domain, (char*)c_username, (char*)c_password, &loginfo); result = status ? JNI_TRUE : JNI_FALSE; shaj_log_debug(&loginfo, "checking password for domain=%s user=%s => %d", (c_domain==NULL)? "(NULL)" : c_domain, c_username, (int) result); if (aDomain != NULL) { (*jvm)->ReleaseStringUTFChars(jvm, aDomain, c_domain); } (*jvm)->ReleaseStringUTFChars(jvm, aUsername, c_username); (*jvm)->ReleaseStringUTFChars(jvm, aPassword, c_password); return result; }
jboolean shaj_chkpasswd_pam(const char* service, const char *user, const char *password, loginfo_t* logger){ pam_handle_t *pamh = 0; int status = -1; struct pam_conv pc; struct ourpam_authdata c; c.user = user; c.password = password; c.logger = logger; pc.conv = &ourpam_conversation; pc.appdata_ptr = (void *) &c; status = mypam_start(service, c.user, &pc, &pamh); shaj_log_debug(logger, "pam_start (\"%s\", \"%s\", ...) ==> %d (%s)", service, c.user, status, PAM_STRERROR (pamh, status)); if (status != PAM_SUCCESS) goto DONE; status = mypam_authenticate(pamh, 0); shaj_log_debug(logger, " pam_authenticate (...) ==> %d (%s)", status, PAM_STRERROR(pamh, status)); if (status == PAM_SUCCESS) { /* be nice to Kerberos and refresh credentials */ int status2 = mypam_setcred(pamh, PAM_REINITIALIZE_CRED); shaj_log_debug(logger, " pam_setcred (...) ==> %d (%s)", status2, PAM_STRERROR(pamh, status2)); goto DONE; } DONE: if (pamh) { int status2 = mypam_end(pamh, status); pamh = 0; shaj_log_debug(logger, "pam_end (...) ==> %d (%s)", status2, (status2 == PAM_SUCCESS ? "Success" : "Failure")); } return (status == PAM_SUCCESS ? JNI_TRUE : JNI_FALSE); }
/* return 1 on success */ static jboolean mypam__init(loginfo_t* logger) { if (logger->isdebug) { shaj_log_debug(logger, "attempting to load libpam.so"); } libpam = dlopen ("libpam.so", RTLD_NOW | RTLD_GLOBAL); if (libpam == NULL) { shaj_log_error(logger, "Could not dlopen libpam.so with RTLD_NOW|RTLD_GLOBAL: %s\n", dlerror());; return JNI_FALSE; } real_pam_start = (FUNC_pam_start*) mydlsym(libpam, "pam_start", logger); if (real_pam_start == NULL) { return JNI_FALSE; } real_pam_end = (FUNC_pam_end*) mydlsym(libpam, "pam_end", logger); if (real_pam_end == NULL) { return JNI_FALSE; } real_pam_authenticate = (FUNC_pam_authenticate*) mydlsym(libpam, "pam_authenticate", logger); if (real_pam_authenticate == NULL) { return JNI_FALSE; } real_pam_strerror = (FUNC_pam_strerror*) mydlsym(libpam, "pam_strerror", logger); if (real_pam_strerror == NULL) { return JNI_FALSE; } real_pam_setcred = (FUNC_pam_setcred*) mydlsym(libpam, "pam_setcred", logger); if (real_pam_setcred == NULL) { return JNI_FALSE; } return JNI_TRUE; }
static int ourpam_conversation(int nmsgs, #ifndef OS_IS_SOLARIS const #endif struct pam_message **msg, struct pam_response **resp, void *authdatap) { /* * strings we pass to PAM in the reply objects are freed by * PAM as described here * http://www.opengroup.org/onlinepubs/8329799/chap5.htm */ int replies = 0; struct pam_response *reply = 0; struct ourpam_authdata *authdata = (struct ourpam_authdata *) authdatap; loginfo_t* logger = authdata->logger; reply = (struct pam_response *) calloc(nmsgs, sizeof(*reply)); if (!reply) return PAM_CONV_ERR; for (replies = 0; replies < nmsgs; replies++) { switch (msg[replies]->msg_style) { case PAM_PROMPT_ECHO_ON: reply[replies].resp_retcode = PAM_SUCCESS; reply[replies].resp = strdup(authdata->user); shaj_log_debug(logger, " PAM ECHO_ON(\"%s\") ==> \"%s\"", msg[replies]->msg, reply[replies].resp); break; case PAM_PROMPT_ECHO_OFF: reply[replies].resp_retcode = PAM_SUCCESS; reply[replies].resp = strdup(authdata->password); shaj_log_debug(logger, " PAM ECHO_OFF(\"%s\") ==> password", /*msg[replies]->msg*/ "(masked)"); break; case PAM_TEXT_INFO: /* ignore */ reply[replies].resp_retcode = PAM_SUCCESS; reply[replies].resp = 0; shaj_log_debug(logger, " PAM TEXT_INFO(\"%s\") ==> ignored", msg[replies]->msg); break; case PAM_ERROR_MSG: /* ignore it */ reply[replies].resp_retcode = PAM_SUCCESS; reply[replies].resp = 0; shaj_log_debug(logger, " PAM ERROR_MSG(\"%s\") ==> ignored", msg[replies]->msg); break; default: /* fail at this point */ free (reply); shaj_log_error(logger, " PAM unknown %d(\"%s\") ==> ignored", msg[replies]->msg_style, msg[replies]->msg); return PAM_CONV_ERR; } } *resp = reply; return PAM_SUCCESS; }
BOOL GenServerContext(PAUTH_SEQ pAS, PVOID pIn, DWORD cbIn, PVOID pOut, PDWORD pcbOut, PBOOL pfDone, loginfo_t* logger) { /*++ Routine Description: Takes an input buffer coming from the client and returns a buffer to be sent to the client. Also returns an indication of whether or not the context is complete. Return Value: Returns TRUE if successful; otherwise FALSE. --*/ SECURITY_STATUS ss; TimeStamp tsExpiry; SecBufferDesc sbdOut; SecBuffer sbOut; SecBufferDesc sbdIn; SecBuffer sbIn; ULONG fContextAttr; if (!pAS->fInitialized) { ss = _AcquireCredentialsHandle(NULL, _T("NTLM"), SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &pAS->hcred, &tsExpiry); if (ss < 0) { shaj_log_error(logger, "AcquireCredentialsHandle failed with %08X\n", ss); return FALSE; } pAS->fHaveCredHandle = TRUE; } // Prepare output buffer sbdOut.ulVersion = 0; sbdOut.cBuffers = 1; sbdOut.pBuffers = &sbOut; sbOut.cbBuffer = *pcbOut; sbOut.BufferType = SECBUFFER_TOKEN; sbOut.pvBuffer = pOut; // Prepare input buffer sbdIn.ulVersion = 0; sbdIn.cBuffers = 1; sbdIn.pBuffers = &sbIn; sbIn.cbBuffer = cbIn; sbIn.BufferType = SECBUFFER_TOKEN; sbIn.pvBuffer = pIn; ss = _AcceptSecurityContext(&pAS->hcred, pAS->fInitialized ? &pAS->hctxt : NULL, &sbdIn, 0, SECURITY_NATIVE_DREP, &pAS->hctxt, &sbdOut, &fContextAttr, &tsExpiry); if (ss < 0) { shaj_log_debug(logger, "AcceptSecurityContext failed with %08X\n", ss); return FALSE; } pAS->fHaveCtxtHandle = TRUE; // If necessary, complete token if (ss == SEC_I_COMPLETE_NEEDED || ss == SEC_I_COMPLETE_AND_CONTINUE) { if (_CompleteAuthToken) { ss = _CompleteAuthToken(&pAS->hctxt, &sbdOut); if (ss < 0) { shaj_log_debug(logger, "CompleteAuthToken failed with %08X\n", ss); return FALSE; } } else { shaj_log_debug(logger, "CompleteAuthToken not supported.\n"); return FALSE; } } *pcbOut = sbOut.cbBuffer; if (!pAS->fInitialized) pAS->fInitialized = TRUE; *pfDone = !(ss = SEC_I_CONTINUE_NEEDED || ss == SEC_I_COMPLETE_AND_CONTINUE); return TRUE; }