int main(int argc, char **argv) { char pname[ANAME_SZ + 1], pinst[INST_SZ + 1]; CREDENTIALS cred; int ret; ret = tf_init(tkt_string(), R_TKT_FIL); if (ret != 0) { printf("Error initializing ticket file \"%s\".\n", tkt_string()); return ret; } memset(&cred, 0, sizeof(cred)); ret = tf_get_pname(pname); if (ret != 0) { printf("Error reading names from \"%s\".\n", tkt_string()); return ret; } ret = tf_get_pinst(pinst); if (ret != 0) { printf("Error reading names from \"%s\".\n", tkt_string()); return ret; } ret = tf_get_cred(&cred); if (ret != 0) { printf("Error reading creds from \"%s\".\n", tkt_string()); return ret; } printf("%lu\n", (unsigned long) cred.lifetime); tf_close(); return 0; }
int krb_get_cred( char *service, /* Service name */ char *instance, /* Instance */ char *realm, /* Auth domain */ CREDENTIALS *c /* Credentials struct */ ) { int tf_status; /* return value of tf function calls */ struct timeval local_time; int kinited = 0; char env[16]; BOOL prompt; GetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT",env, sizeof(env)); prompt = (GetLastError() == ERROR_ENVVAR_NOT_FOUND); c->pname[0] = c->pinst[0] = '\0'; check_cache: gettimeofday(&local_time, 0); /* Open ticket file and lock it for shared reading */ if ((tf_status = tf_init(TKT_FILE, R_TKT_FIL)) != KSUCCESS) { goto cache_checked; } /* Copy principal's name and instance into the CREDENTIALS struc c */ if (((tf_status = tf_get_pname(c->pname)) != KSUCCESS) || ((tf_status = tf_get_pinst(c->pinst)) != KSUCCESS)) { goto cache_checked; } /* Search for requested service credentials and copy into c */ while ((tf_status = tf_get_cred(c)) == KSUCCESS) { /* Is this the right ticket? */ if (!service || (strcmp(c->service,service) == 0) && (!instance || strcmp(c->instance,instance) == 0) && (!realm || strcmp(c->realm,realm) == 0)) { // Hey, is this a valid ticket? Let's check before we return. if (((long)((c->issue_date + c->lifetime * 5L * 60L) - (long)local_time.tv_sec) >= 0) && ( 0 == com_addr(c))) { break; // we're OK } } } cache_checked: tf_close(); // If we are requesting a tgt, prompt for it if (tf_status != KSUCCESS && !kinited && strncmp(service, "krbtgt", ANAME_SZ) == 0 && prompt) { static int (*pLeash_kinit_dlg_ex)(HWND hParent, LPLSH_DLGINFO_EX lpdlginfoex) = 0; static DWORD (*pLeash_get_default_use_krb4)() = 0; kinited = 1; if ( !m_hLeashDLL ) { m_hLeashDLL = LoadLibrary(LEASHDLL); if ( m_hLeashDLL ) { (FARPROC)pLeash_kinit_dlg_ex=GetProcAddress(m_hLeashDLL,"Leash_kinit_dlg_ex"); (FARPROC)pLeash_get_default_use_krb4=GetProcAddress(m_hLeashDLL,"Leash_get_default_use_krb4"); } } if ( pLeash_get_default_use_krb4 && pLeash_kinit_dlg_ex ) { LSH_DLGINFO_EX dlginfo; int success; // copy in the existing username and realm char * pTmp = calloc(1, strlen(c->pname) + strlen(c->pinst) + 2); strcpy(pTmp, c->pname); if (c->pname[0] != 0 && c->pinst[0] != 0) { strcat(pTmp, "/"); strcat(pTmp, c->pinst); } memset(&dlginfo, 0, sizeof(LSH_DLGINFO_EX)); dlginfo.size = sizeof(LSH_DLGINFO_EX); dlginfo.dlgtype = DLGTYPE_PASSWD; dlginfo.title = dlginfo.in.title; strcpy(dlginfo.in.title,"Kerberos 4 - Obtain Tickets"); dlginfo.username = dlginfo.in.username; strcpy(dlginfo.in.username,pTmp); dlginfo.realm = dlginfo.in.realm; strcpy(dlginfo.in.realm,realm); dlginfo.use_defaults = 1; success = pLeash_kinit_dlg_ex(GetDesktopWindow(), &dlginfo); free(pTmp); if (success) goto check_cache; } } if (tf_status == EOF) return (GC_NOTKT); return(tf_status); }
static int _pam_krb5_v4_init(krb5_context ctx, struct _pam_krb5_stash *stash, struct _pam_krb5_user_info *user, struct _pam_krb5_options *options, char *sname, char *sinstance, char *password, int *result) { char name[ANAME_SZ + 1], instance[INST_SZ + 1], realm[REALM_SZ + 1]; char pname[ANAME_SZ + 1], pinstance[INST_SZ + 1]; char tktfile[PATH_MAX]; char *saved_tktstring; int life, i, fd; struct stat st; /* Convert the krb5 version of the principal's name to a v4 principal * name. This may involve changing "host" to "rcmd" and so on, so let * libkrb5 handle it. */ memset(name, '\0', sizeof(name)); memset(instance, '\0', sizeof(instance)); memset(realm, '\0', sizeof(realm)); i = krb5_524_conv_principal(ctx, user->principal_name, name, instance, realm); if (i != 0) { if (result) { *result = i; } return PAM_SERVICE_ERR; } if (options->debug) { debug("converted principal to '%s%s%s%s@'%s'", name, strlen(instance) ? "'.'" : "'", instance, strlen(instance) ? "'" : "", realm); } #ifdef HAVE_KRB_TIME_TO_LIFE /* Convert the ticket lifetime of the v5 credentials into a v4 * lifetime, which is the X coordinate along a curve where Y is the * actual length. Again, this is magic. */ life = krb_time_to_life(stash->v5creds.times.starttime, stash->v5creds.times.endtime); #else /* No life_to_time() function means that we have to estimate the * intended lifetime, in 5-minute increments. We also have a maximum * value to contend with, because the lifetime is expressed in a single * byte. */ life = stash->v5creds.times.endtime - stash->v5creds.times.starttime; life /= (60 * 5); if (life > 0xff) { life = 0xff; } #endif /* Create the ticket file. One of two things will happen here. Either * libkrb[4] will just use the file, and we're safer because it * wouldn't have used O_EXCL to do so, or it will nuke the file and * reopen it with O_EXCL. In the latter case, the descriptor we have * will become useless, so we don't actually use it for anything. */ #ifdef HAVE_LONG_LONG snprintf(tktfile, sizeof(tktfile), "%s/tkt%llu_XXXXXX", options->ccache_dir, options->user_check ? (unsigned long long) user->uid : (unsigned long long) getuid()); #else snprintf(tktfile, sizeof(tktfile), "%s/tkt%lu_XXXXXX", options->ccache_dir, options->user_check ? (unsigned long) user->uid : (unsigned long) getuid()); #endif fd = mkstemp(tktfile); if (fd == -1) { if (result) { *result = errno; } 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("preparing to place v4 credentials in '%s'", tktfile); } /* Save the old default ticket file name, and set the default to use * our just-created empty file. */ saved_tktstring = xstrdup(tkt_string()); krb_set_tkt_string(tktfile); /* Get the initial credentials. */ i = krb_get_pw_in_tkt(name, instance, realm, sname, sinstance ? sinstance : realm, life, password); if (result) { *result = i; } /* Restore the original default ticket file name. */ krb_set_tkt_string(saved_tktstring); xstrfree(saved_tktstring); saved_tktstring = NULL; /* If we got credentials, read them from the file, and then remove the * file. */ if (i == 0) { i = tf_init(tktfile, R_TKT_FIL); if (i == 0) { i = tf_get_pname(pname); if (i == 0) { i = tf_get_pinst(pinstance); if (i == 0) { i = tf_get_cred(&stash->v4creds); if (i == 0) { tf_close(); unlink(tktfile); close(fd); return PAM_SUCCESS; } else { warn("error reading creds " "from '%s': %d (%s)", tktfile, i, v5_error_message(i)); } } else { warn("error reading instance from '%s'" ": %d (%s)", tktfile, i, v5_error_message(i)); } } else { warn("error reading principal name from '%s'" ": %d (%s)", tktfile, i, v5_error_message(i)); } tf_close(); } else { 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 '%s' for reading: %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()); } } } } unlink(tktfile); close(fd); return PAM_AUTH_ERR; }