/* Store the v4 TGT in $KRBTKFILE. */ static void sly_v4(krb5_context ctx, const char *v4tktfile, struct _pam_krb5_user_info *userinfo, struct _pam_krb5_stash *stash) { int i; char name[ANAME_SZ + 1], instance[INST_SZ + 1], realm[REALM_SZ + 1]; i = krb5_524_conv_principal(ctx, userinfo->principal_name, name, instance, realm); if (i != 0) { return; } tf_init((char *) v4tktfile, W_TKT_FIL); v4_in_tkt(name, instance, realm); v4_save_credentials(KRB5_TGS_NAME, realm, realm, stash->v4creds.session, stash->v4creds.lifetime, stash->v4creds.kvno, &stash->v4creds.ticket_st, stash->v4creds.issue_date); tf_close(); }
static int v4_save(krb5_context ctx, struct _pam_krb5_stash *stash, struct _pam_krb5_user_info *userinfo, struct _pam_krb5_options *options, uid_t uid, gid_t gid, const char **ccname, int clone_cc) { char name[ANAME_SZ + 1], instance[INST_SZ + 1], realm[REALM_SZ + 1]; char tktfile[PATH_MAX]; char *saved_tktstring; int i, fd; struct stat st; if (ccname != NULL) { *ccname = NULL; } /* Convert the v5 principal name into v4 notation. */ memset(name, '\0', sizeof(name)); memset(instance, '\0', sizeof(instance)); memset(realm, '\0', sizeof(realm)); if (stash->v5creds.client != NULL) { /* Use the client principal of the creds we have, which we * can assume are always correct, even if "external" somehow * got us to the point where the principal name in "userinfo" * is incorrect. */ i = krb5_524_conv_principal(ctx, stash->v5creds.client, name, instance, realm); } else { /* Use the parsed principal as a fallback. We should never * really get here, but just in case. */ i = krb5_524_conv_principal(ctx, userinfo->principal_name, name, instance, realm); } if (i != 0) { warn("error converting %s to a Kerberos IV principal " "(shouldn't happen)", userinfo->unparsed_name); return PAM_SERVICE_ERR; } /* Create a new ticket file. */ #ifdef HAVE_LONG_LONG snprintf(tktfile, sizeof(tktfile), "%s/tkt%llu_XXXXXX", options->ccache_dir, options->user_check ? (unsigned long long) userinfo->uid : (unsigned long long) getuid()); #else snprintf(tktfile, sizeof(tktfile), "%s/tkt%lu_XXXXXX", options->ccache_dir, options->user_check ? (unsigned long) userinfo->uid : (unsigned long) getuid()); #endif fd = mkstemp(tktfile); if (fd == -1) { warn("error creating unique Kerberos IV ticket file " "(shouldn't happen)"); return PAM_SERVICE_ERR; } if (fchown(fd, getuid(), getgid()) != 0) { warn("error setting permissions on \"%s\" (%s), attempting " "to continue", tktfile, strerror(errno)); } if (options->debug) { debug("saving v4 tickets to '%s'", tktfile); } /* Open the ticket file. */ saved_tktstring = xstrdup(tkt_string()); krb_set_tkt_string(tktfile); i = tf_init(tktfile, W_TKT_FIL); if (i != 0) { const char *tferror; switch (i) { case NO_TKT_FIL: tferror = "no ticket file"; break; case TKT_FIL_ACC: tferror = "ticket file had wrong permissions"; break; case TKT_FIL_LCK: tferror = "error locking ticket file"; break; default: tferror = strerror(errno); break; } warn("error opening ticket file '%s': %s", tktfile, tferror); if ((i == TKT_FIL_ACC) && (options->debug)) { if (stat(tktfile, &st) == 0) { debug("file owner is %lu:%lu, " "we are effective %lu:%lu, " "real %lu:%lu", (unsigned long) st.st_uid, (unsigned long) st.st_gid, (unsigned long) geteuid(), (unsigned long) getegid(), (unsigned long) getuid(), (unsigned long) getgid()); } } krb_set_tkt_string(saved_tktstring); xstrfree(saved_tktstring); unlink(tktfile); close(fd); return PAM_SERVICE_ERR; } /* Store the user's name. */ if (v4_in_tkt(name, instance, realm) != 0) { warn("error initializing ticket file '%s'", tktfile); tf_close(); krb_set_tkt_string(saved_tktstring); xstrfree(saved_tktstring); unlink(tktfile); close(fd); return PAM_SERVICE_ERR; } /* Store the v4 credentials. */ if (v4_save_credentials(KRB5_TGS_NAME, realm, realm, stash->v4creds.session, stash->v4creds.lifetime, stash->v4creds.kvno, &stash->v4creds.ticket_st, stash->v4creds.issue_date) != 0) { warn("error saving tickets to '%s'", tktfile); tf_close(); krb_set_tkt_string(saved_tktstring); xstrfree(saved_tktstring); unlink(tktfile); close(fd); return PAM_SERVICE_ERR; } /* Close the new file. */ tf_close(); xstrfree(saved_tktstring); close(fd); /* Save the new file's name in the stash, and optionally return it to * the caller. */ if (_pam_krb5_stash_push_v4(ctx, stash, options, tktfile) == 0) { /* Generate a *new* ticket file with the same contents as this * one. */ if (clone_cc) { _pam_krb5_stash_clone_v4(stash, uid, gid); } krb_set_tkt_string(stash->v4tktfiles->name); if (ccname != NULL) { *ccname = stash->v4tktfiles->name; } } return PAM_SUCCESS; }