static int save_krb5_creds (int s, krb5_auth_context auth_context, krb5_principal client) { int ret; krb5_data remote_cred; krb5_data_zero (&remote_cred); ret= krb5_read_message (context, (void *)&s, &remote_cred); if (ret) { krb5_data_free(&remote_cred); return 0; } if (remote_cred.length == 0) return 0; ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); if (ret) { krb5_data_free(&remote_cred); return 0; } krb5_cc_initialize(context,ccache,client); ret = krb5_rd_cred2(context, auth_context, ccache, &remote_cred); if(ret != 0) syslog(LOG_INFO|LOG_AUTH, "reading creds: %s", krb5_get_err_text(context, ret)); krb5_data_free (&remote_cred); if (ret) return 0; return 1; }
static OM_uint32 gsskrb5_accept_delegated_token (OM_uint32 * minor_status, gsskrb5_ctx ctx, krb5_context context, gss_cred_id_t * delegated_cred_handle ) { krb5_ccache ccache = NULL; krb5_error_code kret; int32_t ac_flags, ret = GSS_S_COMPLETE; *minor_status = 0; /* XXX Create a new delegated_cred_handle? */ if (delegated_cred_handle == NULL) { kret = krb5_cc_default (context, &ccache); } else { *delegated_cred_handle = NULL; kret = krb5_cc_new_unique (context, krb5_cc_type_memory, NULL, &ccache); } if (kret) { ctx->flags &= ~GSS_C_DELEG_FLAG; goto out; } kret = krb5_cc_initialize(context, ccache, ctx->source); if (kret) { ctx->flags &= ~GSS_C_DELEG_FLAG; goto out; } krb5_auth_con_removeflags(context, ctx->auth_context, KRB5_AUTH_CONTEXT_DO_TIME, &ac_flags); kret = krb5_rd_cred2(context, ctx->auth_context, ccache, &ctx->fwd_data); krb5_auth_con_setflags(context, ctx->auth_context, ac_flags); if (kret) { ctx->flags &= ~GSS_C_DELEG_FLAG; ret = GSS_S_FAILURE; *minor_status = kret; goto out; } if (delegated_cred_handle) { gsskrb5_cred handle; ret = _gsskrb5_krb5_import_cred(minor_status, ccache, NULL, NULL, delegated_cred_handle); if (ret != GSS_S_COMPLETE) goto out; handle = (gsskrb5_cred) *delegated_cred_handle; handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; krb5_cc_close(context, ccache); ccache = NULL; } out: if (ccache) { /* Don't destroy the default cred cache */ if (delegated_cred_handle == NULL) krb5_cc_close(context, ccache); else krb5_cc_destroy(context, ccache); } return ret; }
void kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) { krb5_error_code ret; krb5_data outbuf; krb5_keyblock *key_block; char *name; krb5_principal server; int zero = 0; if (cnt-- < 1) return; switch (*data++) { case KRB_AUTH: auth.data = (char *)data; auth.length = cnt; auth_context = NULL; ret = krb5_auth_con_init (context, &auth_context); if (ret) { Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } ret = krb5_auth_con_setaddrs_from_fd (context, auth_context, &zero); if (ret) { Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } ret = krb5_sock_to_principal (context, 0, "host", KRB5_NT_SRV_HST, &server); if (ret) { Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_sock_to_principal failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } ret = krb5_rd_req(context, &auth_context, &auth, server, NULL, NULL, &ticket); krb5_free_principal (context, server); if (ret) { char *errbuf; asprintf(&errbuf, "Read req failed: %s", krb5_get_err_text(context, ret)); Data(ap, KRB_REJECT, errbuf, -1); if (auth_debug_mode) printf("%s\r\n", errbuf); free (errbuf); return; } { char foo[2]; foo[0] = ap->type; foo[1] = ap->way; ret = krb5_verify_authenticator_checksum(context, auth_context, foo, sizeof(foo)); if (ret) { char *errbuf; asprintf(&errbuf, "Bad checksum: %s", krb5_get_err_text(context, ret)); Data(ap, KRB_REJECT, errbuf, -1); if (auth_debug_mode) printf ("%s\r\n", errbuf); free(errbuf); return; } } ret = krb5_auth_con_getremotesubkey (context, auth_context, &key_block); if (ret) { Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_auth_con_getremotesubkey failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } if (key_block == NULL) { ret = krb5_auth_con_getkey(context, auth_context, &key_block); } if (ret) { Data(ap, KRB_REJECT, "krb5_auth_con_getkey failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_auth_con_getkey failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } if (key_block == NULL) { Data(ap, KRB_REJECT, "no subkey received", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_auth_con_getremotesubkey returned NULL key\r\n"); return; } if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { ret = krb5_mk_rep(context, auth_context, &outbuf); if (ret) { Data(ap, KRB_REJECT, "krb5_mk_rep failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_mk_rep failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); } if (krb5_unparse_name(context, ticket->client, &name)) name = 0; if(UserNameRequested && krb5_kuserok(context, ticket->client, UserNameRequested)) { Data(ap, KRB_ACCEPT, name, name ? -1 : 0); if (auth_debug_mode) { printf("Kerberos5 identifies him as ``%s''\r\n", name ? name : ""); } if(key_block->keytype == ETYPE_DES_CBC_MD5 || key_block->keytype == ETYPE_DES_CBC_MD4 || key_block->keytype == ETYPE_DES_CBC_CRC) { Session_Key skey; skey.type = SK_DES; skey.length = 8; skey.data = key_block->keyvalue.data; encrypt_session_key(&skey, 0); } } else { char *msg; asprintf (&msg, "user `%s' is not authorized to " "login as `%s'", name ? name : "<unknown>", UserNameRequested ? UserNameRequested : "<nobody>"); if (msg == NULL) Data(ap, KRB_REJECT, NULL, 0); else { Data(ap, KRB_REJECT, (void *)msg, -1); free(msg); } auth_finished (ap, AUTH_REJECT); krb5_free_keyblock_contents(context, key_block); break; } auth_finished(ap, AUTH_USER); krb5_free_keyblock_contents(context, key_block); break; case KRB_FORWARD: { struct passwd *pwd; char ccname[1024]; /* XXX */ krb5_data inbuf; krb5_ccache ccache; inbuf.data = (char *)data; inbuf.length = cnt; pwd = getpwnam (UserNameRequested); if (pwd == NULL) break; snprintf (ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%u", pwd->pw_uid); ret = krb5_cc_resolve (context, ccname, &ccache); if (ret) { if (auth_debug_mode) printf ("Kerberos V5: could not get ccache: %s\r\n", krb5_get_err_text(context, ret)); break; } ret = krb5_cc_initialize (context, ccache, ticket->client); if (ret) { if (auth_debug_mode) printf ("Kerberos V5: could not init ccache: %s\r\n", krb5_get_err_text(context, ret)); break; } #if defined(DCE) esetenv("KRB5CCNAME", ccname, 1); #endif ret = krb5_rd_cred2 (context, auth_context, ccache, &inbuf); if(ret) { char *errbuf; asprintf (&errbuf, "Read forwarded creds failed: %s", krb5_get_err_text (context, ret)); if(errbuf == NULL) Data(ap, KRB_FORWARD_REJECT, NULL, 0); else Data(ap, KRB_FORWARD_REJECT, errbuf, -1); if (auth_debug_mode) printf("Could not read forwarded credentials: %s\r\n", errbuf); free (errbuf); } else { Data(ap, KRB_FORWARD_ACCEPT, 0, 0); #if defined(DCE) dfsfwd = 1; #endif } chown (ccname + 5, pwd->pw_uid, -1); if (auth_debug_mode) printf("Forwarded credentials obtained\r\n"); break; } default: if (auth_debug_mode) printf("Unknown Kerberos option %d\r\n", data[-1]); Data(ap, KRB_REJECT, 0, 0); break; } }
static int proto (int sock, const char *svc) { krb5_auth_context auth_context; krb5_error_code status; krb5_principal server; krb5_ticket *ticket; char *name; char ret_string[10]; char hostname[MAXHOSTNAMELEN]; krb5_data data; krb5_data remotename; krb5_data tk_file; krb5_ccache ccache; char ccname[MAXPATHLEN]; struct passwd *pwd; status = krb5_auth_con_init (context, &auth_context); if (status) krb5_err(context, 1, status, "krb5_auth_con_init"); status = krb5_auth_con_setaddrs_from_fd (context, auth_context, &sock); if (status) krb5_err(context, 1, status, "krb5_auth_con_setaddr"); if(gethostname (hostname, sizeof(hostname)) < 0) krb5_err(context, 1, errno, "gethostname"); status = krb5_sname_to_principal (context, hostname, svc, KRB5_NT_SRV_HST, &server); if (status) krb5_err(context, 1, status, "krb5_sname_to_principal"); status = krb5_recvauth_match_version (context, &auth_context, &sock, kfd_match_version, NULL, server, 0, NULL, &ticket); if (status) krb5_err(context, 1, status, "krb5_recvauth"); status = krb5_unparse_name (context, ticket->client, &name); if (status) krb5_err(context, 1, status, "krb5_unparse_name"); if(protocol_version == 0) { data.data = "old clnt"; /* XXX old clients only had room for 10 bytes of message, and also didn't show it to the user */ data.length = strlen(data.data) + 1; krb5_write_message(context, &sock, &data); sleep(2); /* XXX give client time to finish */ krb5_errx(context, 1, "old client; exiting"); } status=krb5_read_priv_message (context, auth_context, &sock, &remotename); if (status) krb5_err(context, 1, status, "krb5_read_message"); status=krb5_read_priv_message (context, auth_context, &sock, &tk_file); if (status) krb5_err(context, 1, status, "krb5_read_message"); krb5_data_zero (&data); if(((char*)remotename.data)[remotename.length-1] != '\0') krb5_errx(context, 1, "unterminated received"); if(((char*)tk_file.data)[tk_file.length-1] != '\0') krb5_errx(context, 1, "unterminated received"); status = krb5_read_priv_message(context, auth_context, &sock, &data); if (status) { krb5_err(context, 1, errno, "krb5_read_priv_message"); goto out; } pwd = getpwnam ((char *)(remotename.data)); if (pwd == NULL) { status=1; krb5_warnx(context, "getpwnam: %s failed",(char *)(remotename.data)); goto out; } if(!krb5_kuserok (context, ticket->client, (char *)(remotename.data))) { status=1; krb5_warnx(context, "krb5_kuserok: permission denied"); goto out; } if (setgid(pwd->pw_gid) < 0) { krb5_warn(context, errno, "setgid"); goto out; } if (setuid(pwd->pw_uid) < 0) { krb5_warn(context, errno, "setuid"); goto out; } if (tk_file.length != 1) snprintf (ccname, sizeof(ccname), "%s", (char *)(tk_file.data)); else snprintf (ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%lu", (unsigned long)pwd->pw_uid); status = krb5_cc_resolve (context, ccname, &ccache); if (status) { krb5_warn(context, status, "krb5_cc_resolve"); goto out; } status = krb5_cc_initialize (context, ccache, ticket->client); if (status) { krb5_warn(context, status, "krb5_cc_initialize"); goto out; } status = krb5_rd_cred2 (context, auth_context, ccache, &data); krb5_cc_close (context, ccache); if (status) { krb5_warn(context, status, "krb5_rd_cred"); goto out; } strlcpy(krb5_tkfile,ccname,sizeof(krb5_tkfile)); krb5_warnx(context, "%s forwarded ticket to %s,%s", name, (char *)(remotename.data),ccname); out: if (status) { strlcpy(ret_string, "no", sizeof(ret_string)); krb5_warnx(context, "failed"); } else { strlcpy(ret_string, "ok", sizeof(ret_string)); } krb5_data_free (&tk_file); krb5_data_free (&remotename); krb5_data_free (&data); free(name); data.data = ret_string; data.length = strlen(ret_string) + 1; status = krb5_write_priv_message(context, auth_context, &sock, &data); krb5_auth_con_free(context, auth_context); return status; }
int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt) { krb5_error_code problem; krb5_ccache ccache = NULL; char *pname; const char *errtxt; if (authctxt->pw == NULL || authctxt->krb5_user == NULL) return (0); temporarily_use_uid(authctxt->pw); problem = krb5_cc_new_unique(authctxt->krb5_ctx, "FILE", NULL, &ccache); if (problem) goto fail; problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, authctxt->krb5_user); if (problem) goto fail; problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, ccache, tgt); if (problem) goto fail; authctxt->krb5_fwd_ccache = ccache; ccache = NULL; authctxt->krb5_ticket_file = __UNCONST(krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache)); problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user, &pname); if (problem) goto fail; #ifdef USE_PAM if (options.use_pam) do_pam_putenv(__UNCONST("KRB5CCNAME"), authctxt->krb5_ticket_file); #endif debug("Kerberos v5 TGT accepted (%s)", pname); restore_uid(); return (1); fail: if (problem) { errtxt = krb5_get_error_message(authctxt->krb5_ctx, problem); if (errtxt != NULL) { debug("Kerberos v5 TGT passing failed: %s", errtxt); krb5_free_error_message(authctxt->krb5_ctx, errtxt); } else debug("Kerberos v5 TGT passing failed: %d", problem); } if (ccache) krb5_cc_destroy(authctxt->krb5_ctx, ccache); restore_uid(); return (0); }
int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt) { krb5_error_code problem; krb5_ccache ccache = NULL; char *pname; krb5_creds **creds; if (authctxt->pw == NULL || authctxt->krb5_user == NULL) return (0); temporarily_use_uid(authctxt->pw); #ifdef HEIMDAL problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &ccache); #else { char ccname[40]; int tmpfd; snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid()); if ((tmpfd = mkstemp(ccname+strlen("FILE:")))==-1) { log("mkstemp(): %.100s", strerror(errno)); problem = errno; goto fail; } if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { log("fchmod(): %.100s", strerror(errno)); close(tmpfd); problem = errno; goto fail; } close(tmpfd); problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &ccache); } #endif if (problem) goto fail; problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, authctxt->krb5_user); if (problem) goto fail; #ifdef HEIMDAL problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, ccache, tgt); if (problem) goto fail; #else problem = krb5_rd_cred(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, tgt, &creds, NULL); if (problem) goto fail; problem = krb5_cc_store_cred(authctxt->krb5_ctx, ccache, *creds); if (problem) goto fail; #endif authctxt->krb5_fwd_ccache = ccache; ccache = NULL; authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user, &pname); if (problem) goto fail; debug("Kerberos v5 TGT accepted (%s)", pname); restore_uid(); return (1); fail: if (problem) debug("Kerberos v5 TGT passing failed: %s", krb5_get_err_text(authctxt->krb5_ctx, problem)); if (ccache) krb5_cc_destroy(authctxt->krb5_ctx, ccache); restore_uid(); return (0); }