OM_uint32 GSSAPI_LIB_FUNCTION gss_acquire_cred_ex(const gss_name_t desired_name, OM_uint32 flags, OM_uint32 time_req, gss_const_OID desired_mech, gss_cred_usage_t cred_usage, gss_auth_identity_t identity, gss_acquire_cred_complete complete) { OM_uint32 ret; complete = (gss_acquire_cred_complete)Block_copy(complete); ret = gss_acquire_cred_ex_f(NULL, desired_name, flags, time_req, desired_mech, cred_usage, identity, complete, complete_block); if (ret != GSS_S_COMPLETE) Block_release(complete); return ret; }
static int smb_acquire_cred(const char *user, const char *domain, const char *password, gss_OID mech, void **gssCreds) { gss_auth_identity_desc identity; struct smb_gss_cred_ctx aq_cred_ctx; uint32_t maj = !GSS_S_COMPLETE; if (password == NULL || user == NULL || *user == '\0') return 0; identity.type = GSS_AUTH_IDENTITY_TYPE_1; identity.flags = 0; identity.username = strdup(user); identity.realm = strdup(domain ? domain : ""); identity.password = strdup(password); identity.credentialsRef = NULL; if (identity.username == NULL || identity.realm == NULL || identity.password == NULL) goto out; aq_cred_ctx.sem = dispatch_semaphore_create(0); if (aq_cred_ctx.sem == NULL) goto out; maj = gss_acquire_cred_ex_f(NULL, GSS_C_NO_NAME, 0, GSS_C_INDEFINITE, mech, GSS_C_INITIATE, &identity, &aq_cred_ctx, acquire_cred_complete); if (maj == GSS_S_COMPLETE) { dispatch_semaphore_wait(aq_cred_ctx.sem, DISPATCH_TIME_FOREVER); maj = aq_cred_ctx.maj; *gssCreds = aq_cred_ctx.creds; } if (maj != GSS_S_COMPLETE) smb_log_info("Acquiring NTLM creds for %s\%s failed. GSS returned %d", ASL_LEVEL_INFO, domain, user, maj); dispatch_release(aq_cred_ctx.sem); out: free(identity.username); free(identity.realm); free(identity.password); return (maj == GSS_S_COMPLETE); }
int /* O - 0 on success, -1 on error */ _cupsSetNegotiateAuthString( http_t *http, /* I - Connection to server */ const char *method, /* I - Request method ("GET", "POST", "PUT") */ const char *resource) /* I - Resource path */ { OM_uint32 minor_status, /* Minor status code */ major_status; /* Major status code */ gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; /* Output token */ (void)method; (void)resource; # ifdef __APPLE__ /* * If the weak-linked GSSAPI/Kerberos library is not present, don't try * to use it... */ if (&gss_init_sec_context == NULL) { DEBUG_puts("1_cupsSetNegotiateAuthString: Weak-linked GSSAPI/Kerberos " "framework is not present"); return (-1); } # endif /* __APPLE__ */ if (http->gssname == GSS_C_NO_NAME) { http->gssname = cups_gss_getname(http, _cupsGSSServiceName()); } if (http->gssctx != GSS_C_NO_CONTEXT) { gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER); http->gssctx = GSS_C_NO_CONTEXT; } major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL, &http->gssctx, http->gssname, http->gssmech, GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG, GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER, &http->gssmech, &output_token, NULL, NULL); #ifdef HAVE_GSS_ACQUIRE_CRED_EX_F if (major_status == GSS_S_NO_CRED) { /* * Ask the user for credentials... */ char prompt[1024], /* Prompt for user */ userbuf[256]; /* Kerberos username */ const char *username, /* Username string */ *password; /* Password string */ _cups_gss_acquire_t data; /* Callback data */ gss_auth_identity_desc identity; /* Kerberos user identity */ _cups_globals_t *cg = _cupsGlobals(); /* Per-thread global data */ if (!cg->lang_default) cg->lang_default = cupsLangDefault(); snprintf(prompt, sizeof(prompt), _cupsLangString(cg->lang_default, _("Password for %s on %s? ")), cupsUser(), http->gsshost); if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL) return (-1); /* * Try to acquire credentials... */ username = cupsUser(); if (!strchr(username, '@')) { snprintf(userbuf, sizeof(userbuf), "%s@%s", username, http->gsshost); username = userbuf; } identity.type = GSS_AUTH_IDENTITY_TYPE_1; identity.flags = 0; identity.username = (char *)username; identity.realm = (char *)""; identity.password = (char *)password; identity.credentialsRef = NULL; data.sem = dispatch_semaphore_create(0); data.major = 0; data.creds = NULL; if (data.sem) { major_status = gss_acquire_cred_ex_f(NULL, GSS_C_NO_NAME, 0, GSS_C_INDEFINITE, GSS_KRB5_MECHANISM, GSS_C_INITIATE, &identity, &data, cups_gss_acquire); if (major_status == GSS_S_COMPLETE) { dispatch_semaphore_wait(data.sem, DISPATCH_TIME_FOREVER); major_status = data.major; } dispatch_release(data.sem); if (major_status == GSS_S_COMPLETE) { OM_uint32 release_minor; /* Minor status from releasing creds */ major_status = gss_init_sec_context(&minor_status, data.creds, &http->gssctx, http->gssname, http->gssmech, GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG, GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER, &http->gssmech, &output_token, NULL, NULL); gss_release_cred(&release_minor, &data.creds); } } } #endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */ if (GSS_ERROR(major_status)) { cups_gss_printf(major_status, minor_status, "_cupsSetNegotiateAuthString: Unable to initialize " "security context"); return (-1); } #ifdef DEBUG else if (major_status == GSS_S_CONTINUE_NEEDED) cups_gss_printf(major_status, minor_status, "_cupsSetNegotiateAuthString: Continuation needed!"); #endif /* DEBUG */ if (output_token.length > 0 && output_token.length <= 65536) { /* * Allocate the authorization string since Windows KDCs can have * arbitrarily large credentials... */ int authsize = 10 + /* "Negotiate " */ (int)output_token.length * 4 / 3 + 1 + 1; /* Base64 + nul */ httpSetAuthString(http, NULL, NULL); if ((http->authstring = malloc((size_t)authsize)) == NULL) { http->authstring = http->_authstring; authsize = sizeof(http->_authstring); } strlcpy(http->authstring, "Negotiate ", (size_t)authsize); httpEncode64_2(http->authstring + 10, authsize - 10, output_token.value, (int)output_token.length); gss_release_buffer(&minor_status, &output_token); } else { DEBUG_printf(("1_cupsSetNegotiateAuthString: Kerberos credentials too " "large - %d bytes!", (int)output_token.length)); gss_release_buffer(&minor_status, &output_token); return (-1); } return (0); }
static int test_scram(const char *test_name, const char *user, const char *password) { gss_name_t cname, target = GSS_C_NO_NAME; OM_uint32 maj_stat, min_stat; gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; gss_buffer_desc cn, input, output, output2; int ret; heim_scram *scram = NULL; heim_scram_data in, out; gss_auth_identity_desc identity; memset(&identity, 0, sizeof(identity)); identity.username = rk_UNCONST(user); identity.realm = ""; identity.password = rk_UNCONST(password); cn.value = rk_UNCONST(user); cn.length = strlen(user); maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname); if (maj_stat) errx(1, "gss_import_name: %d", (int)maj_stat); maj_stat = gss_acquire_cred_ex_f(NULL, cname, 0, GSS_C_INDEFINITE, GSS_SCRAM_MECHANISM, GSS_C_INITIATE, &identity, NULL, ac_complete); if (maj_stat) errx(1, "gss_acquire_cred_ex_f: %d", (int)maj_stat); if (client_cred == GSS_C_NO_CREDENTIAL) errx(1, "gss_acquire_cred_ex_f"); cn.value = rk_UNCONST("host@localhost"); cn.length = strlen((char *)cn.value); maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_HOSTBASED_SERVICE, &target); if (maj_stat) errx(1, "gss_import_name: %d", (int)maj_stat); maj_stat = gss_init_sec_context(&min_stat, client_cred, &ctx, target, GSS_SCRAM_MECHANISM, 0, 0, NULL, GSS_C_NO_BUFFER, NULL, &output, NULL, NULL); if (maj_stat != GSS_S_CONTINUE_NEEDED) errx(1, "accept_sec_context %s %s", test_name, gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); if (output.length == 0) errx(1, "output.length == 0"); maj_stat = gss_decapsulate_token(&output, GSS_SCRAM_MECHANISM, &output2); if (maj_stat) errx(1, "decapsulate token"); in.length = output2.length; in.data = output2.value; ret = heim_scram_server1(&in, NULL, HEIM_SCRAM_DIGEST_SHA1, &server_proc, NULL, &scram, &out); if (ret) errx(1, "heim_scram_server1"); gss_release_buffer(&min_stat, &output); input.length = out.length; input.value = out.data; maj_stat = gss_init_sec_context(&min_stat, client_cred, &ctx, target, GSS_SCRAM_MECHANISM, 0, 0, NULL, &input, NULL, &output, NULL, NULL); if (maj_stat != GSS_S_CONTINUE_NEEDED) { warnx("accept_sec_context v1 2 %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); return 1; } in.length = output.length; in.data = output.value; ret = heim_scram_server2(&in, scram, &out); if (ret) errx(1, "heim_scram_server2"); gss_release_buffer(&min_stat, &output); input.length = out.length; input.value = out.data; maj_stat = gss_init_sec_context(&min_stat, client_cred, &ctx, target, GSS_SCRAM_MECHANISM, 0, 0, NULL, &input, NULL, &output, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { warnx("accept_sec_context v1 2 %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); return 1; } heim_scram_free(scram); //gss_destroy_cred(NULL, &client_cred); printf("done: %s\n", test_name); return 0; }