afs_int32 ka_GetAuthToken(char *name, char *instance, char *cell, struct ktc_encryptionKey * key, afs_int32 lifetime, afs_int32 * pwexpires) { afs_int32 code; struct ubik_client *conn; afs_int32 now = time(0); struct ktc_token token; char cellname[MAXKTCREALMLEN]; char realm[MAXKTCREALMLEN]; struct ktc_principal client, server; LOCK_GLOBAL_MUTEX; code = ka_ExpandCell(cell, cellname, 0 /*local */ ); if (code) { UNLOCK_GLOBAL_MUTEX; return code; } cell = cellname; /* get an unauthenticated connection to desired cell */ code = ka_AuthServerConn(cell, KA_AUTHENTICATION_SERVICE, 0, &conn); if (code) { UNLOCK_GLOBAL_MUTEX; return code; } code = ka_Authenticate(name, instance, cell, conn, KA_TICKET_GRANTING_SERVICE, key, now, now + lifetime, &token, pwexpires); if (code) { UNLOCK_GLOBAL_MUTEX; return code; } code = ubik_ClientDestroy(conn); if (code) { UNLOCK_GLOBAL_MUTEX; return code; } code = ka_CellToRealm(cell, realm, 0 /*local */ ); if (code) { UNLOCK_GLOBAL_MUTEX; return code; } strcpy(client.name, name); strcpy(client.instance, instance); strncpy(client.cell, cell, sizeof(client.cell)); strcpy(server.name, KA_TGS_NAME); strcpy(server.instance, realm); strcpy(server.cell, cell); code = ktc_SetToken(&server, &token, &client, 0); UNLOCK_GLOBAL_MUTEX; return code; }
/* * Build a list of tokens, delete the bad ones (the ones to remove from the * permissions list,) destroy all tokens, and then re-register the good ones. * Ugly, but it works. */ int uss_fs_UnlogToken(char *celln) { int count = 0, index, index2; afs_int32 code = 0, cnt = 0; struct ktc_principal serviceName; struct tokenInfo *tokenInfoP, *tp; do { code = ktc_ListTokens(count, &count, &serviceName); cnt++; } while (!code); count = cnt - 1; tokenInfoP = malloc((sizeof(struct tokenInfo) * count)); for (code = index = index2 = 0; (!code) && (index < count); index++) { tp = tokenInfoP + index; code = ktc_ListTokens(index2, &index2, &tp->service); if (!code) { code = ktc_GetToken(&tp->service, &tp->token, sizeof(struct ktc_token), &tp->client); if (!code) { tp->deleted = (!strcmp(celln, tp->client.cell) ? 1 : 0); if (tp->deleted) cnt = 1; } } } if ((code = ktc_ForgetAllTokens())) { printf("uss_fs_UnlogToken: could not discard tickets, code %d\n", code); exit(1); } for (code = index = 0; index < count; index++) { tp = tokenInfoP + index; if (!(tp->deleted)) { code = ktc_SetToken(&tp->service, &tp->token, &tp->client, 0); if (code) { printf ("uss_fs_UnlogToken: Couldn't re-register token, code = %d\n", code); } } } return 0; }
int afs_set_token(struct afs_auth_creds afscreds ) { /* * Set tokens in kernel */ int afs_status; char buf[1024]; int buflen=0; afs_int32 viceId; /* * Initialize afs? and map the afs user (client.name) to an id */ atc_log_debug("Initialize afs client?"); if (afs_status=pr_Initialize(0,AFSDIR_CLIENT_ETC_DIRPATH,afscreds.server.cell)) { sprintf(afs_token_cache_errmsg,"Failed to initialize afs stuff for cell '%s'",afscreds.server.cell); goto fail; } atc_log_debug("Mapping username to afs pts id"); if ( afs_status=afs_status=pr_SNameToId(afscreds.client.name,&viceId)) { sprintf(afs_token_cache_errmsg,"Failed to map name '%s' to id",afscreds.client.name); goto fail; } /* * Set the token if the afs id is greater than 0 and not anonymous (32766) */ if ( viceId != 32766 && viceId > 0 ) { atc_log_info("Setting afs tokens in kernel for user '%s'", afscreds.client.name); afs_status=ktc_SetToken(&afscreds.server, &afscreds.token, &afscreds.client, 0); if ( afs_status ) { sprintf(afs_token_cache_errmsg, "Failed to set tokens in kernel for user '%s'", afscreds.client.name); goto fail; } } else { atc_log_info("User id is either 0 or the afs anonymous id (32766), not setting tokens"); } return 0; fail: atc_log_err(afs_token_cache_errmsg); return 1; }
static int unlog_ForgetCertainTokens(char **list, int listSize) { int index, index2; int count; afs_int32 code; struct ktc_principal serviceName; struct tokenInfo *tokenInfoP; /* normalize all the names in the list */ unlog_NormalizeCellNames(list, listSize); /* figure out how many tokens exist */ count = 0; do { code = ktc_ListTokens(count, &count, &serviceName); } while (!code); tokenInfoP = (struct tokenInfo *)malloc((sizeof(struct tokenInfo) * count)); if (!tokenInfoP) { perror("unlog_ForgetCertainTokens -- osi_Alloc failed"); exit(1); } for (code = index = index2 = 0; (!code) && (index < count); index++) { code = ktc_ListTokens(index2, &index2, &(tokenInfoP + index)->service); if (!code) { code = ktc_GetToken(&(tokenInfoP + index)->service, &(tokenInfoP + index)->token, sizeof(struct ktc_token), &(tokenInfoP + index)->client); if (!code) (tokenInfoP + index)->deleted = unlog_CheckUnlogList(list, listSize, &(tokenInfoP + index)->client); } } unlog_VerifyUnlog(list, listSize, tokenInfoP, count); code = ktc_ForgetAllTokens(); if (code) { printf("unlog: could not discard tickets, code %d\n", code); exit(1); } for (code = index = 0; index < count; index++) { if (!((tokenInfoP + index)->deleted)) { code = ktc_SetToken(&(tokenInfoP + index)->service, &(tokenInfoP + index)->token, &(tokenInfoP + index)->client, 0); if (code) { fprintf(stderr, "Couldn't re-register token, code = %d\n", code); } } } return 0; }
/* * Log to a cell. If the cell has already been logged to, return without * doing anything. Otherwise, log to it and mark that it has been logged * to. */ static int auth_to_cell(krb5_context context, char *user, char *cell, char *realm) { int status = 0; char username[BUFSIZ]; /* To hold client username structure */ afs_int32 viceId; /* AFS uid of user */ char name[ANAME_SZ]; /* Name of afs key */ char primary_instance[INST_SZ]; /* Instance of afs key */ char secondary_instance[INST_SZ]; /* Backup instance to try */ int try_secondary = 0; /* Flag to indicate if we try second */ char realm_of_user[REALM_SZ]; /* Kerberos realm of user */ char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */ char local_cell[MAXCELLCHARS+1]; char cell_to_use[MAXCELLCHARS+1]; /* Cell to authenticate to */ static char lastcell[MAXCELLCHARS+1] = { 0 }; static char confname[512] = { 0 }; krb5_creds *v5cred = NULL; struct ktc_principal aserver; struct ktc_principal aclient; struct ktc_token atoken, btoken; int afssetpag = 0, uid = -1; struct passwd *pwd; memset(name, 0, sizeof(name)); memset(primary_instance, 0, sizeof(primary_instance)); memset(secondary_instance, 0, sizeof(secondary_instance)); memset(realm_of_user, 0, sizeof(realm_of_user)); memset(realm_of_cell, 0, sizeof(realm_of_cell)); syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog starting: user %s uid %d", user, getuid()); if (confname[0] == '\0') { strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname)); confname[sizeof(confname) - 2] = '\0'; } /* NULL or empty cell returns information on local cell */ if ((status = get_cellconfig(cell, &ak_cellconfig, local_cell, linkedcell))) { syslog(LOG_AUTH|LOG_ERR, "LAM aklog: get_cellconfig returns %d", status); return(status); } strncpy(cell_to_use, ak_cellconfig.name, MAXCELLCHARS); cell_to_use[MAXCELLCHARS] = 0; /* * Find out which realm we're supposed to authenticate to. If one * is not included, use the kerberos realm found in the credentials * cache. */ if (realm && realm[0]) { strcpy(realm_of_cell, realm); } else { char *afs_realm = afs_realm_of_cell(context, &ak_cellconfig, FALSE); if (!afs_realm) { syslog(LOG_AUTH|LOG_ERR, "LAM aklog: afs_realm_of_cell returns %d", status); return AFSCONF_FAILURE; } strcpy(realm_of_cell, afs_realm); } /* We use the afs.<cellname> convention here... * * Doug Engert's original code had principals of the form: * * "afsx/cell@realm" * * in the KDC, so the name wouldn't conflict with DFS. Since we're * not using DFS, I changed it just to look for the following * principals: * * afs/<cell>@<realm> * afs@<realm> * * Because people are transitioning from afs@realm to afs/cell, * we configure things so that if the first one isn't found, we * try the second one. You can select which one you prefer with * a configure option. */ strcpy(name, AFSKEY); if (1 || strcasecmp(cell_to_use, realm_of_cell) != 0) { strncpy(primary_instance, cell_to_use, sizeof(primary_instance)); primary_instance[sizeof(primary_instance)-1] = '\0'; if (strcasecmp(cell_to_use, realm_of_cell) == 0) { try_secondary = 1; secondary_instance[0] = '\0'; } } else { primary_instance[0] = '\0'; try_secondary = 1; strncpy(secondary_instance, cell_to_use, sizeof(secondary_instance)); secondary_instance[sizeof(secondary_instance)-1] = '\0'; } /* * Extract the session key from the ticket file and hand-frob an * afs style authenticator. */ /* * Try to obtain AFS tickets. Because there are two valid service * names, we will try both, but trying the more specific first. * * afs/<cell>@<realm> i.e. allow for single name with "." * afs@<realm> */ status = get_credv5(context, user, name, primary_instance, realm_of_cell, &v5cred); if ((status == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || status == KRB5KRB_ERR_GENERIC) && !realm_of_cell[0]) { char *afs_realm = afs_realm_of_cell(context, &ak_cellconfig, TRUE); if (!afs_realm) { syslog(LOG_AUTH|LOG_ERR, "LAM aklog: afs_realm_of_cell returns %d", status); return AFSCONF_FAILURE; } strcpy(realm_of_cell, afs_realm); if (strcasecmp(cell_to_use, realm_of_cell) == 0) { try_secondary = 1; secondary_instance[0] = '\0'; } status = get_credv5(context, user, name, primary_instance, realm_of_cell, &v5cred); } if (status == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || status == KRB5KRB_ERR_GENERIC) { if (try_secondary) status = get_credv5(context, user, name, secondary_instance, realm_of_cell, &v5cred); } if (status) { syslog(LOG_AUTH|LOG_ERR, "LAM aklog: get_credv5 returns %d", status); return status; } strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1); strncpy(aserver.instance, AFSINST, MAXKTCNAMELEN - 1); strncpy(aserver.cell, cell_to_use, MAXKTCREALMLEN - 1); /* * The default is to use rxkad2b, which means we put in a full * V5 ticket. If the user specifies -524, we talk to the * 524 ticket converter. */ { char *p; int len; len = min(get_princ_len(context, v5cred->client, 0), second_comp(context, v5cred->client) ? MAXKTCNAMELEN - 2 : MAXKTCNAMELEN - 1); strncpy(username, get_princ_str(context, v5cred->client, 0), len); username[len] = '\0'; if (second_comp(context, v5cred->client)) { strcat(username, "."); p = username + strlen(username); len = min(get_princ_len(context, v5cred->client, 1), MAXKTCNAMELEN - strlen(username) - 1); strncpy(p, get_princ_str(context, v5cred->client, 1), len); p[len] = '\0'; } memset(&atoken, 0, sizeof(atoken)); atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5; atoken.startTime = v5cred->times.starttime;; atoken.endTime = v5cred->times.endtime; memcpy(&atoken.sessionKey, get_cred_keydata(v5cred), get_cred_keylen(v5cred)); atoken.ticketLen = v5cred->ticket.length; memcpy(atoken.ticket, v5cred->ticket.data, atoken.ticketLen); } if ((status = get_user_realm(context, realm_of_user))) { syslog(LOG_AUTH|LOG_ERR, "LAM aklog: get_user_realm returns %d", status); return KRB5_REALM_UNKNOWN; } if (strcmp(realm_of_user, realm_of_cell)) { strcat(username, "@"); strcat(username, realm_of_user); } strcpy(lastcell, aserver.cell); /* * This is a crock, but it is Transarc's crock, so * we have to play along in order to get the * functionality. The way the afs id is stored is * as a string in the username field of the token. * Contrary to what you may think by looking at * the code for tokens, this hack (AFS ID %d) will * not work if you change %d to something else. */ #if 0 /* This actually crashes long-running daemons */ if (!pr_Initialize (0, confname, aserver.cell)) status = pr_SNameToId (username, &viceId); if ((status == 0) && (viceId != ANONYMOUSID)) sprintf (username, "AFS ID %d", (int) viceId); #else /* * This actually only works assuming that your uid and pts space match * and probably this works only for the local cell anyway. */ if ((uid = getuid()) == 0) { if ((pwd = getpwnam(user)) == NULL) { syslog(LOG_AUTH|LOG_ERR, "LAM aklog: getpwnam %s failed", user); return AUTH_FAILURE; } } /* Don't do first-time registration. Handle only the simple case */ if ((status == 0) && (viceId != ANONYMOUSID)) sprintf (username, "AFS ID %d", ((uid==0)?(int)pwd->pw_uid:(int)uid)); #endif /* Reset the "aclient" structure before we call ktc_SetToken. * This structure was first set by the ktc_GetToken call when * we were comparing whether identical tokens already existed. */ strncpy(aclient.name, username, MAXKTCNAMELEN - 1); strcpy(aclient.instance, ""); strncpy(aclient.cell, realm_of_user, MAXKTCREALMLEN - 1); #ifndef AFS_AIX51_ENV /* on AIX 4.1.4 with AFS 3.4a+ if a write is not done before * this routine, it will not add the token. It is not clear what * is going on here! So we will do the following operation. * On AIX 5 this kills our parent. So we won't. */ write(2,"",0); /* dummy write */ #endif afssetpag = (getpagvalue("afs") > 0) ? 1 : 0; if (uid == 0) { struct sigaction newAction, origAction; pid_t cid, pcid; int wstatus; sigemptyset(&newAction.sa_mask); newAction.sa_handler = SIG_DFL; newAction.sa_flags = 0; status = sigaction(SIGCHLD, &newAction, &origAction); if (status) { syslog(LOG_AUTH|LOG_ERR, "LAM aklog: sigaction returned %d", status); return AUTH_FAILURE; } syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: in daemon? forking to set tokens"); cid = fork(); if (cid <= 0) { syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog child: setting tokens"); setuid(pwd->pw_uid); status = ktc_SetToken(&aserver, &atoken, &aclient, afssetpag); if (status != 0) syslog(LOG_AUTH|LOG_ERR, "LAM aklog child: set tokens, returning %d", status); exit((status == 0)?0:255); } else { do { pcid = waitpid(cid, &wstatus, 0); } while ((pcid == -1) && (errno == EINTR)); if ((pcid == cid) && WIFEXITED(wstatus)) status = WEXITSTATUS(wstatus); else status = -1; } syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: collected child status %d", status); sigaction(SIGCHLD, &origAction, NULL); } else { status = ktc_SetToken(&aserver, &atoken, &aclient, afssetpag); } if (status != 0) syslog(LOG_AUTH|LOG_ERR, "LAM aklog: set tokens returned %d", status); else syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: set tokens, pag %d", getpagvalue("afs")); return(status); }
int main(int argc, char **argv) { char localName[64]; register afs_int32 code; register char *cname; struct afsconf_dir *tdir; struct ktc_principal tserver; struct ktc_token token; strcpy(whoami, argv[0]); if (argc <= 1) { printf ("%s: copies a file system ticket from the local cell to another cell\n", whoami); printf("%s: usage is 'setauth <new-cell>\n", whoami); exit(1); } cname = argv[1]; /* lookup the name of the local cell */ tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH); if (!tdir) { printf("copyauth: can't open dir %s\n", AFSDIR_CLIENT_ETC_DIRPATH); exit(1); } code = afsconf_GetLocalCell(tdir, localName, sizeof(localName)); if (code) { printf("%s: can't determine local cell name\n", whoami); exit(1); } /* done with configuration stuff now */ afsconf_Close(tdir); /* get ticket in local cell */ strcpy(tserver.cell, localName); strcpy(tserver.name, "afs"); tserver.instance[0] = 0; code = ktc_GetToken(&tserver, &token, sizeof(token), NULL); if (code) { printf ("%s: failed to get '%s' service ticket in cell '%s' (code %d)\n", whoami, tserver.name, tserver.cell, code); exit(1); } /* and now set the ticket in the new cell */ strcpy(tserver.cell, argv[1]); code = ktc_SetToken(&tserver, &token, NULL, 0); if (code) { printf ("%s: failed to set ticket (code %d), are you sure you're authenticated?\n", whoami, code); exit(1); } /* all done */ printf("Authentication established for cell %s.\n", cname); exit(0); }
static int CommandProc(struct cmd_syndesc *as, void *arock) { krb5_principal princ = 0; char *cell, *pname, **hrealms, *service; char service_temp[MAXKTCREALMLEN + 20]; krb5_creds incred[1], mcred[1], *outcred = 0, *afscred; krb5_ccache cc = 0; #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC krb5_get_init_creds_opt *gic_opts; #else krb5_get_init_creds_opt gic_opts[1]; #endif char *tofree = NULL, *outname; int code; char *what; int i, dosetpag, evil, noprdb, id; #ifdef AFS_RXK5 int authtype; #endif krb5_data enc_part[1]; krb5_prompter_fct pf = NULL; char *pass = 0; void *pa = 0; struct kp_arg klog_arg[1]; char passwd[BUFSIZ]; struct afsconf_cell cellconfig[1]; static char rn[] = "klog"; /*Routine name */ static int Pipe = 0; /* reading from a pipe */ static int Silent = 0; /* Don't want error messages */ int writeTicketFile = 0; /* write ticket file to /tmp */ service = 0; memset(incred, 0, sizeof *incred); /* blow away command line arguments */ for (i = 1; i < zero_argc; i++) memset(zero_argv[i], 0, strlen(zero_argv[i])); zero_argc = 0; memset(klog_arg, 0, sizeof *klog_arg); /* first determine quiet flag based on -silent switch */ Silent = (as->parms[aSILENT].items ? 1 : 0); if (Silent) { afs_set_com_err_hook(silent_errors); } if ((code = krb5_init_context(&k5context))) { afs_com_err(rn, code, "while initializing Kerberos 5 library"); KLOGEXIT(code); } if ((code = rx_Init(0))) { afs_com_err(rn, code, "while initializing rx"); KLOGEXIT(code); } initialize_U_error_table(); /*initialize_krb5_error_table();*/ initialize_RXK_error_table(); initialize_KTC_error_table(); initialize_ACFG_error_table(); /* initialize_rx_error_table(); */ if (!(tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) { afs_com_err(rn, 0, "can't get afs configuration (afsconf_Open(%s))", AFSDIR_CLIENT_ETC_DIRPATH); KLOGEXIT(1); } /* * Enable DES enctypes, which are currently still required for AFS. * krb5_allow_weak_crypto is MIT Kerberos 1.8. krb5_enctype_enable is * Heimdal. */ #if defined(HAVE_KRB5_ENCTYPE_ENABLE) i = krb5_enctype_valid(k5context, ETYPE_DES_CBC_CRC); if (i) krb5_enctype_enable(k5context, ETYPE_DES_CBC_CRC); #elif defined(HAVE_KRB5_ALLOW_WEAK_CRYPTO) krb5_allow_weak_crypto(k5context, 1); #endif /* Parse remaining arguments. */ dosetpag = !! as->parms[aSETPAG].items; Pipe = !! as->parms[aPIPE].items; writeTicketFile = !! as->parms[aTMP].items; noprdb = !! as->parms[aNOPRDB].items; evil = (always_evil&1) || !! as->parms[aUNWRAP].items; #ifdef AFS_RXK5 authtype = 0; if (as->parms[aK5].items) authtype |= FORCE_RXK5; if (as->parms[aK4].items) authtype |= FORCE_RXKAD; if (!authtype) authtype |= env_afs_rxk5_default(); #endif cell = as->parms[aCELL].items ? as->parms[aCELL].items->data : 0; if ((code = afsconf_GetCellInfo(tdir, cell, "afsprot", cellconfig))) { if (cell) afs_com_err(rn, code, "Can't get cell information for '%s'", cell); else afs_com_err(rn, code, "Can't get determine local cell!"); KLOGEXIT(code); } if (as->parms[aKRBREALM].items) { code = krb5_set_default_realm(k5context, as->parms[aKRBREALM].items->data); if (code) { afs_com_err(rn, code, "Can't make <%s> the default realm", as->parms[aKRBREALM].items->data); KLOGEXIT(code); } } else if ((code = krb5_get_host_realm(k5context, cellconfig->hostName[0], &hrealms))) { afs_com_err(rn, code, "Can't get realm for host <%s> in cell <%s>\n", cellconfig->hostName[0], cellconfig->name); KLOGEXIT(code); } else { if (hrealms && *hrealms) { code = krb5_set_default_realm(k5context, *hrealms); if (code) { afs_com_err(rn, code, "Can't make <%s> the default realm", *hrealms); KLOGEXIT(code); } } if (hrealms) krb5_free_host_realm(k5context, hrealms); } id = getuid(); if (as->parms[aPRINCIPAL].items) { pname = as->parms[aPRINCIPAL].items->data; } else { /* No explicit name provided: use Unix uid. */ struct passwd *pw; pw = getpwuid(id); if (pw == 0) { afs_com_err(rn, 0, "Can't figure out your name from your user id (%d).", id); if (!Silent) fprintf(stderr, "%s: Try providing the user name.\n", rn); KLOGEXIT(1); } pname = pw->pw_name; } code = krb5_parse_name(k5context, pname, &princ); if (code) { afs_com_err(rn, code, "Can't parse principal <%s>", pname); KLOGEXIT(code); } if (as->parms[aPASSWORD].items) { /* * Current argument is the desired password string. Remember it in * our local buffer, and zero out the argument string - anyone can * see it there with ps! */ strncpy(passwd, as->parms[aPASSWORD].items->data, sizeof(passwd)); memset(as->parms[aPASSWORD].items->data, 0, strlen(as->parms[aPASSWORD].items->data)); pass = passwd; } /* Get the password if it wasn't provided. */ if (!pass) { if (Pipe) { strncpy(passwd, getpipepass(), sizeof(passwd)); pass = passwd; } else { pf = klog_prompter; pa = klog_arg; } } service = 0; #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) { tofree = get_afs_krb5_svc_princ(cellconfig); snprintf(service_temp, sizeof service_temp, "%s", tofree); } else #endif snprintf (service_temp, sizeof service_temp, "afs/%s", cellconfig->name); klog_arg->pp = &pass; klog_arg->pstore = passwd; klog_arg->allocated = sizeof(passwd); /* XXX should allow k5 to prompt in most cases -- what about expired pw?*/ #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC code = krb5_get_init_creds_opt_alloc(k5context, &gic_opts); if (code) { afs_com_err(rn, code, "Can't allocate get_init_creds options"); KLOGEXIT(code); } #else krb5_get_init_creds_opt_init(gic_opts); #endif for (;;) { code = krb5_get_init_creds_password(k5context, incred, princ, pass, pf, /* prompter */ pa, /* data */ 0, /* start_time */ 0, /* in_tkt_service */ gic_opts); if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) break; } memset(passwd, 0, sizeof(passwd)); if (code) { char *r = 0; if (krb5_get_default_realm(k5context, &r)) r = 0; if (r) afs_com_err(rn, code, "Unable to authenticate in realm %s", r); else afs_com_err(rn, code, "Unable to authenticate to use cell %s", cellconfig->name); if (r) free(r); KLOGEXIT(code); } for (;;writeTicketFile = 0) { if (writeTicketFile) { what = "getting default ccache"; code = krb5_cc_default(k5context, &cc); } else { what = "krb5_cc_resolve"; code = krb5_cc_resolve(k5context, "MEMORY:core", &cc); if (code) goto Failed; } what = "initializing ccache"; code = krb5_cc_initialize(k5context, cc, princ); if (code) goto Failed; what = "writing Kerberos ticket file"; code = krb5_cc_store_cred(k5context, cc, incred); if (code) goto Failed; if (writeTicketFile) fprintf(stderr, "Wrote ticket file to %s\n", krb5_cc_get_name(k5context, cc)); break; Failed: if (code) afs_com_err(rn, code, "%s", what); if (writeTicketFile) { if (cc) { krb5_cc_close(k5context, cc); cc = 0; } continue; } KLOGEXIT(code); } for (service = service_temp;;service = "afs") { memset(mcred, 0, sizeof *mcred); mcred->client = princ; code = krb5_parse_name(k5context, service, &mcred->server); if (code) { afs_com_err(rn, code, "Unable to parse service <%s>\n", service); KLOGEXIT(code); } if (tofree) { free(tofree); tofree = 0; } if (!(code = krb5_unparse_name(k5context, mcred->server, &outname))) tofree = outname; else outname = service; code = krb5_get_credentials(k5context, 0, cc, mcred, &outcred); krb5_free_principal(k5context, mcred->server); if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break; #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) break; #endif } afscred = outcred; if (code) { afs_com_err(rn, code, "Unable to get credentials to use %s", outname); KLOGEXIT(code); } #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) { struct ktc_principal aserver[1]; int viceid = 555; memset(aserver, 0, sizeof *aserver); strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1); code = ktc_SetK5Token(k5context, aserver, afscred, viceid, dosetpag); if (code) { afs_com_err(rn, code, "Unable to store tokens for cell %s\n", cellconfig->name); KLOGEXIT(1); } } else #endif { struct ktc_principal aserver[1], aclient[1]; struct ktc_token atoken[1]; memset(atoken, 0, sizeof *atoken); if (evil) { size_t elen = enc_part->length; atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY; if (afs_krb5_skip_ticket_wrapper(afscred->ticket.data, afscred->ticket.length, (char **) &enc_part->data, &elen)) { afs_com_err(rn, 0, "Can't unwrap %s AFS credential", cellconfig->name); KLOGEXIT(1); } } else { atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5; *enc_part = afscred->ticket; } atoken->startTime = afscred->times.starttime; atoken->endTime = afscred->times.endtime; if (tkt_DeriveDesKey(get_creds_enctype(afscred), get_cred_keydata(afscred), get_cred_keylen(afscred), &atoken->sessionKey)) { afs_com_err(rn, 0, "Cannot derive DES key from enctype %i of length %u", get_creds_enctype(afscred), (unsigned)get_cred_keylen(afscred)); KLOGEXIT(1); } memcpy(atoken->ticket, enc_part->data, atoken->ticketLen = enc_part->length); memset(aserver, 0, sizeof *aserver); strncpy(aserver->name, "afs", 4); strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1); memset(aclient, 0, sizeof *aclient); i = realm_len(k5context, afscred->client); if (i > MAXKTCREALMLEN-1) i = MAXKTCREALMLEN-1; memcpy(aclient->cell, realm_data(k5context, afscred->client), i); if (!noprdb) { int viceid = 0; k5_to_k4_name(k5context, afscred->client, aclient); code = whoami(atoken, cellconfig, aclient, &viceid); if (code) { afs_com_err(rn, code, "Can't get your viceid for cell %s", cellconfig->name); *aclient->name = 0; } else snprintf(aclient->name, MAXKTCNAMELEN-1, "AFS ID %d", viceid); } if (!*aclient->name) k5_to_k4_name(k5context, afscred->client, aclient); code = ktc_SetToken(aserver, atoken, aclient, dosetpag); if (code) { afs_com_err(rn, code, "Unable to store tokens for cell %s\n", cellconfig->name); KLOGEXIT(1); } } krb5_free_principal(k5context, princ); krb5_free_cred_contents(k5context, incred); if (outcred) krb5_free_creds(k5context, outcred); if (cc) krb5_cc_close(k5context, cc); if (tofree) free(tofree); return 0; }
/* * Requires that you already possess a TGT. */ afs_int32 ka_GetAFSTicket(char *name, char *instance, char *realm, Date lifetime, afs_int32 flags) { afs_int32 code; struct ktc_token token; struct ktc_principal server, client; code = ka_GetServerToken("afs", "", realm, lifetime, &token, /*new */ 1, /*dosetpag */ flags); if (code) return code; if (ktc_OldPioctl()) { int local; char username[MAXKTCNAMELEN]; afs_int32 viceId; int len; char *whoami = "UserAuthenticate: ptserver"; strcpy(server.name, "afs"); strcpy(server.instance, ""); code = ka_ExpandCell(realm, server.cell, &local); if (code) return code; code = pr_Initialize(0, AFSDIR_CLIENT_ETC_DIRPATH, server.cell); if (code) { afs_com_err(whoami, code, "initializing ptserver in cell '%s'", server.cell); return 0; } len = strlen(name); if (instance[0]) len += strlen(instance) + 1; if (len >= sizeof(username)) { fprintf(stderr, "user's name '%s'.'%s' would be too large\n", name, instance); return 0; } strcpy(username, name); if (instance[0]) { strcat(username, "."); strcat(username, instance); } code = pr_SNameToId(username, &viceId); /* Before going further, shutdown the pr ubik connection */ pr_End(); if ((code == 0) && (viceId == ANONYMOUSID)) code = PRNOENT; if (code) { afs_com_err(whoami, code, "translating %s to id", username); return 0; } sprintf(client.name, "AFS ID %d", viceId); strcpy(client.instance, ""); strcpy(client.cell, server.cell); code = ktc_SetToken(&server, &token, &client, /*dosetpag */ 0); if (code) return code; } return code; }
/* * Log to a cell. If the cell has already been logged to, return without * doing anything. Otherwise, log to it and mark that it has been logged * to. */ static int auth_to_cell(krb5_context context, char *cell, char *realm) { int status = AKLOG_SUCCESS; char username[BUFSIZ]; /* To hold client username structure */ char name[ANAME_SZ]; /* Name of afs key */ char instance[INST_SZ]; /* Instance of afs key */ char realm_of_user[REALM_SZ]; /* Kerberos realm of user */ char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */ char local_cell[MAXCELLCHARS+1]; char cell_to_use[MAXCELLCHARS+1]; /* Cell to authenticate to */ krb5_creds *v5cred = NULL; #ifdef HAVE_KRB4 CREDENTIALS c; #endif struct ktc_principal aserver; struct ktc_principal aclient; struct ktc_token atoken, btoken; struct afsconf_cell ak_cellconfig; /* General information about the cell */ int i; int getLinkedCell = 0; /* try to avoid an expensive call to get_cellconfig */ if (cell && ll_string_check(&authedcells, cell)) { if (dflag) printf("Already authenticated to %s (or tried to)\n", cell); return(AKLOG_SUCCESS); } memset(name, 0, sizeof(name)); memset(instance, 0, sizeof(instance)); memset(realm_of_user, 0, sizeof(realm_of_user)); memset(realm_of_cell, 0, sizeof(realm_of_cell)); memset(&ak_cellconfig, 0, sizeof(ak_cellconfig)); /* NULL or empty cell returns information on local cell */ if (status = get_cellconfig(cell, &ak_cellconfig, local_cell)) return(status); linkedCell: if (getLinkedCell) strncpy(cell_to_use, ak_cellconfig.linkedCell, MAXCELLCHARS); else strncpy(cell_to_use, ak_cellconfig.name, MAXCELLCHARS); cell_to_use[MAXCELLCHARS] = 0; if (ll_string_check(&authedcells, cell_to_use)) { if (dflag) printf("Already authenticated to %s (or tried to)\n", cell_to_use); status = AKLOG_SUCCESS; goto done2; } /* * Record that we have attempted to log to this cell. We do this * before we try rather than after so that we will not try * and fail repeatedly for one cell. */ (void)ll_add_string(&authedcells, cell_to_use); if (dflag) printf("Authenticating to cell %s.\n", cell_to_use); /* We use the afs.<cellname> convention here... */ strcpy(name, AFSKEY); strncpy(instance, cell_to_use, sizeof(instance)); instance[sizeof(instance)-1] = '\0'; /* * Extract the session key from the ticket file and hand-frob an * afs style authenticator. */ if (usev5) { /* using krb5 */ int retry = 1; int realm_fallback = 0; if ((status = get_v5_user_realm(context, realm_of_user)) != KSUCCESS) { char * msg; if (pkrb5_get_error_message) msg = pkrb5_get_error_message(context, status); else msg = (char *)error_message(status); fprintf(stderr, "%s: Couldn't determine realm of user: %s\n", progname, msg); if (pkrb5_free_error_message) pkrb5_free_error_message(context, msg); status = AKLOG_KERBEROS; goto done; } if ( strchr(name,'.') != NULL ) { fprintf(stderr, "%s: Can't support principal names including a dot.\n", progname); status = AKLOG_MISC; goto done; } try_v5: if (realm && realm[0]) { if (dflag) printf("Getting v5 tickets: %s/%s@%s\n", name, instance, realm); status = get_v5cred(context, name, instance, realm, #ifdef HAVE_KRB4 use524 ? &c : NULL, #else NULL, #endif &v5cred); strcpy(realm_of_cell, realm); } else { strcpy(realm_of_cell, afs_realm_of_cell5(context, &ak_cellconfig, realm_fallback)); if (retry == 1 && realm_fallback == 0) { /* Only try the realm_of_user once */ status = -1; if (dflag) printf("Getting v5 tickets: %s/%s@%s\n", name, instance, realm_of_user); status = get_v5cred(context, name, instance, realm_of_user, #ifdef HAVE_KRB4 use524 ? &c : NULL, #else NULL, #endif &v5cred); if (status == 0) { /* we have determined that the client realm * is a valid cell realm */ strcpy(realm_of_cell, realm_of_user); } } if (status != 0 && (!retry || retry && strcmp(realm_of_user,realm_of_cell))) { if (dflag) printf("Getting v5 tickets: %s/%s@%s\n", name, instance, realm_of_cell); status = get_v5cred(context, name, instance, realm_of_cell, #ifdef HAVE_KRB4 use524 ? &c : NULL, #else NULL, #endif &v5cred); if (!status && !strlen(realm_of_cell)) copy_realm_of_ticket(context, realm_of_cell, sizeof(realm_of_cell), v5cred); } } if (!realm_fallback && status == KRB5_ERR_HOST_REALM_UNKNOWN) { realm_fallback = 1; goto try_v5; } else if (status == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) { if (!realm_fallback && !realm_of_cell[0]) { realm_fallback = 1; goto try_v5; } if (dflag) printf("Getting v5 tickets: %s@%s\n", name, realm_of_cell); status = get_v5cred(context, name, "", realm_of_cell, #ifdef HAVE_KRB4 use524 ? &c : NULL, #else NULL, #endif &v5cred); if (!status && !strlen(realm_of_cell)) copy_realm_of_ticket(context, realm_of_cell, sizeof(realm_of_cell), v5cred); } if ( status == KRB5KRB_AP_ERR_MSG_TYPE && retry ) { retry = 0; realm_fallback = 0; goto try_v5; } } else { #ifdef HAVE_KRB4 if (realm && realm[0]) strcpy(realm_of_cell, realm); else strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig)); /* * Try to obtain AFS tickets. Because there are two valid service * names, we will try both, but trying the more specific first. * * afs.<cell>@<realm> * afs@<realm> */ if (dflag) printf("Getting tickets: %s.%s@%s\n", name, instance, realm_of_cell); status = get_cred(name, instance, realm_of_cell, &c); if (status == KDC_PR_UNKNOWN) { if (dflag) printf("Getting tickets: %s@%s\n", name, realm_of_cell); status = get_cred(name, "", realm_of_cell, &c); } #else status = AKLOG_MISC; goto done; #endif } if (status != KSUCCESS) { char * msg = NULL; if (dflag) printf("Kerberos error code returned by get_cred: %d\n", status); if (usev5) { if (pkrb5_get_error_message) msg = pkrb5_get_error_message(context, status); else msg = (char *)error_message(status); } #ifdef HAVE_KRB4 else msg = krb_err_text(status); #endif fprintf(stderr, "%s: Couldn't get %s AFS tickets: %s\n", progname, cell_to_use, msg?msg:"(unknown error)"); if (usev5 && pkrb5_free_error_message) pkrb5_free_error_message(context, msg); status = AKLOG_KERBEROS; goto done; } strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1); strncpy(aserver.instance, AFSINST, MAXKTCNAMELEN - 1); strncpy(aserver.cell, cell_to_use, MAXKTCREALMLEN - 1); if (usev5 && !use524) { /* This code inserts the entire K5 ticket into the token * No need to perform a krb524 translation which is * commented out in the code below */ char * p; int len; len = min(v5cred->client->data[0].length,MAXKTCNAMELEN - 1); strncpy(username, v5cred->client->data[0].data, len); username[len] = '\0'; if ( v5cred->client->length > 1 ) { strcat(username, "."); p = username + strlen(username); len = min(v5cred->client->data[1].length, (unsigned int)(MAXKTCNAMELEN - strlen(username) - 1)); strncpy(p, v5cred->client->data[1].data, len); p[len] = '\0'; } memset(&atoken, '\0', sizeof(atoken)); atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5; atoken.startTime = v5cred->times.starttime; atoken.endTime = v5cred->times.endtime; memcpy(&atoken.sessionKey, v5cred->keyblock.contents, v5cred->keyblock.length); atoken.ticketLen = v5cred->ticket.length; memcpy(atoken.ticket, v5cred->ticket.data, atoken.ticketLen); } else { #ifdef HAVE_KRB4 strcpy (username, c.pname); if (c.pinst[0]) { strcat(username, "."); strcat(username, c.pinst); } atoken.kvno = c.kvno; atoken.startTime = c.issue_date; /* ticket lifetime is in five-minutes blocks. */ atoken.endTime = c.issue_date + ((unsigned char)c.lifetime * 5 * 60); memcpy(&atoken.sessionKey, c.session, 8); atoken.ticketLen = c.ticket_st.length; memcpy(atoken.ticket, c.ticket_st.dat, atoken.ticketLen); #else status = AKLOG_MISC; goto done; #endif } if (!force && !ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient) && atoken.kvno == btoken.kvno && atoken.ticketLen == btoken.ticketLen && !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) && !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen)) { if (dflag) printf("Identical tokens already exist; skipping.\n"); status = AKLOG_SUCCESS; goto done2; } if (noprdb) { if (dflag) printf("Not resolving name %s to id (-noprdb set)\n", username); } else { if (!usev5) { #ifdef HAVE_KRB4 if ((status = krb_get_tf_realm(TKT_FILE, realm_of_user)) != KSUCCESS) { fprintf(stderr, "%s: Couldn't determine realm of user: %s)", progname, krb_err_text(status)); status = AKLOG_KERBEROS; goto done; } #else status = AKLOG_MISC; goto done; #endif } /* For Network Identity Manager append the realm to the name */ strcat(username, "@"); strcat(username, realm_of_user); ViceIDToUsername(username, realm_of_user, realm_of_cell, cell_to_use, #ifdef HAVE_KRB4 &c, #else NULL, #endif &status, &aclient, &aserver, &atoken); } if (dflag) printf("Set username to %s\n", username); /* Reset the "aclient" structure before we call ktc_SetToken. * This structure was first set by the ktc_GetToken call when * we were comparing whether identical tokens already existed. */ strncpy(aclient.name, username, MAXKTCNAMELEN - 1); strcpy(aclient.instance, ""); if (usev5 && !use524) { int len = min(v5cred->client->realm.length,MAXKTCNAMELEN - 1); strncpy(aclient.cell, v5cred->client->realm.data, len); aclient.cell[len] = '\0'; } #ifdef HAVE_KRB4 else strncpy(aclient.cell, c.realm, MAXKTCREALMLEN - 1); #endif for ( i=0; aclient.cell[i]; i++ ) { if ( islower(aclient.cell[i]) ) aclient.cell[i] = toupper(aclient.cell[i]); } if (dflag) printf("Getting tokens.\n"); if (status = ktc_SetToken(&aserver, &atoken, &aclient, 0)) { afs_com_err(progname, status, "while obtaining tokens for cell %s\n", cell_to_use); status = AKLOG_TOKEN; } done2: if (ak_cellconfig.linkedCell && !getLinkedCell) { getLinkedCell = 1; goto linkedCell; } done: #if 0 /* * intentionally leak the linkedCell field because it was allocated * using a different C RTL version. */ if (ak_cellconfig.linkedCell) free(ak_cellconfig.linkedCell); #endif return(status); }
void ViceIDToUsername(char *username, char *realm_of_user, char *realm_of_cell, char * cell_to_use, CREDENTIALS *c, int *status, struct ktc_principal *aclient, struct ktc_principal *aserver, struct ktc_token *atoken) { static char lastcell[MAXCELLCHARS+1] = { 0 }; static char confname[512] = { 0 }; char username_copy[BUFSIZ]; afs_int32 viceId; /* AFS uid of user */ if (confname[0] == '\0') { strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname)); confname[sizeof(confname) - 2] = '\0'; } if (dflag) printf("About to resolve name %s to id\n", username); strcpy(lastcell, aserver->cell); if (!pr_Initialize (0, confname, aserver->cell)) { char sname[PR_MAXNAMELEN], *at; strncpy(sname, username, PR_MAXNAMELEN); sname[PR_MAXNAMELEN-1] = '\0'; at = strchr(sname, '@'); if (at && !stricmp(at+1, realm_of_cell)) *at = '\0'; *status = pr_SNameToId (sname, &viceId); } if (dflag) { if (*status) printf("pr_SNameToId Error %s\n", afs_error_message(*status)); else printf("Id %d\n", viceId); } /* * This code is taken from cklog -- it lets people * automatically register with the ptserver in foreign cells */ #ifdef ALLOW_REGISTER if (*status == 0) { if (viceId != ANONYMOUSID) { #else /* ALLOW_REGISTER */ if ((*status == 0) && (viceId != ANONYMOUSID)) #endif /* ALLOW_REGISTER */ { #ifdef AFS_ID_TO_NAME strncpy(username_copy, username, BUFSIZ); snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId); #endif /* AFS_ID_TO_NAME */ } #ifdef ALLOW_REGISTER } else if (strcmp(realm_of_user, realm_of_cell) != 0) { int i; if (dflag) { printf("doing first-time registration of %s " "at %s\n", username, cell_to_use); } strncpy(aclient->name, username, MAXKTCNAMELEN - 1); aclient->name[MAXKTCNAMELEN - 1] = '\0'; strcpy(aclient->instance, ""); strncpy(aclient->cell, cell_to_use, MAXKTCREALMLEN - 1); aclient->cell[MAXKTCREALMLEN - 1] = '\0'; for ( i=0; aclient->cell[i]; i++ ) { if ( islower(aclient->cell[i]) ) aclient->cell[i] = toupper(aclient->cell[i]); } if ((*status = ktc_SetToken(aserver, atoken, aclient, 0))) { afs_com_err(progname, *status, "while obtaining tokens for cell %s\n", cell_to_use); *status = AKLOG_TOKEN; return ; } /* * In case you're wondering, we don't need to change the * filename here because we're still connecting to the * same cell -- we're just using a different authentication * level */ if ((*status = pr_Initialize(1L, confname, aserver->cell))) { printf("pr_Initialize Error %s\n", afs_error_message(*status)); return; } /* copy the name because pr_CreateUser lowercases the realm */ strncpy(username_copy, username, BUFSIZ); viceId = 0; *status = pr_CreateUser(username_copy, &viceId); if (*status) { printf("%s: unable to create remote PTS " "user %s in cell %s (status: %s).\n", progname, username_copy, cell_to_use, afs_error_message(*status)); } else { printf("created cross-cell entry for %s (Id %d) at %s\n", username_copy, viceId, cell_to_use); #ifdef AFS_ID_TO_NAME snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId); #endif /* AFS_ID_TO_NAME */ } } } #endif /* ALLOW_REGISTER */ }
/* * Log to a cell. If the cell has already been logged to, return without * doing anything. Otherwise, log to it and mark that it has been logged * to. */ static int auth_to_cell(char *cell, char *realm) { int status = AKLOG_SUCCESS; char username[BUFSIZ]; /* To hold client username structure */ long viceId; /* AFS uid of user */ char name[ANAME_SZ]; /* Name of afs key */ char instance[INST_SZ]; /* Instance of afs key */ char realm_of_user[REALM_SZ]; /* Kerberos realm of user */ char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */ char local_cell[MAXCELLCHARS+1]; char cell_to_use[MAXCELLCHARS+1]; /* Cell to authenticate to */ int i,j; CREDENTIALS c; struct ktc_principal aserver; struct ktc_principal aclient; struct ktc_token atoken, btoken; /* try to avoid an expensive call to get_cellconfig */ if (cell && ll_string_check(&authedcells, cell)) { if (dflag) printf("Already authenticated to %s (or tried to)\n", cell); return(AKLOG_SUCCESS); } memset(name, 0, sizeof(name)); memset(instance, 0, sizeof(instance)); memset(realm_of_user, 0, sizeof(realm_of_user)); memset(realm_of_cell, 0, sizeof(realm_of_cell)); /* NULL or empty cell returns information on local cell */ if (status = get_cellconfig(cell, &ak_cellconfig, local_cell)) return(status); strncpy(cell_to_use, ak_cellconfig.name, MAXCELLCHARS); cell_to_use[MAXCELLCHARS] = 0; if (ll_string_check(&authedcells, cell_to_use)) { if (dflag) printf("Already authenticated to %s (or tried to)\n", cell_to_use); return(AKLOG_SUCCESS); } /* * Record that we have attempted to log to this cell. We do this * before we try rather than after so that we will not try * and fail repeatedly for one cell. */ (void)ll_add_string(&authedcells, cell_to_use); if (dflag) printf("Authenticating to cell %s.\n", cell_to_use); if (realm && realm[0]) strcpy(realm_of_cell, realm); else strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig)); /* We use the afs.<cellname> convention here... */ strcpy(name, AFSKEY); strncpy(instance, cell_to_use, sizeof(instance)); instance[sizeof(instance)-1] = '\0'; /* * Extract the session key from the ticket file and hand-frob an * afs style authenticator. */ /* * Try to obtain AFS tickets. Because there are two valid service * names, we will try both, but trying the more specific first. * * afs.<cell>@<realm> * afs@<realm> */ if (dflag) printf("Getting tickets: %s.%s@%s\n", name, instance, realm_of_cell); status = get_cred(name, instance, realm_of_cell, &c); if (status == KDC_PR_UNKNOWN) { if (dflag) printf("Getting tickets: %s@%s\n", name, realm_of_cell); status = get_cred(name, "", realm_of_cell, &c); } if (status != KSUCCESS) { if (dflag) printf("Kerberos error code returned by get_cred: %d\n", status); fprintf(stderr, "%s: Couldn't get %s AFS tickets: %s\n", progname, cell_to_use, krb_err_txt[status]); return(AKLOG_KERBEROS); } strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1); strncpy(aserver.instance, AFSINST, MAXKTCNAMELEN - 1); strncpy(aserver.cell, cell_to_use, MAXKTCREALMLEN - 1); strcpy (username, c.pname); if (c.pinst[0]) { strcat(username, "."); strcat(username, c.pinst); } atoken.kvno = c.kvno; atoken.startTime = c.issue_date; /* ticket lifetime is in five-minutes blocks. */ atoken.endTime = c.issue_date + ((unsigned char)c.lifetime * 5 * 60); memcpy(&atoken.sessionKey, c.session, 8); atoken.ticketLen = c.ticket_st.length; memcpy(atoken.ticket, c.ticket_st.dat, atoken.ticketLen); if (!force && !ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient) && atoken.kvno == btoken.kvno && atoken.ticketLen == btoken.ticketLen && !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) && !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen)) { if (dflag) printf("Identical tokens already exist; skipping.\n"); return 0; } if (noprdb) { if (dflag) printf("Not resolving name %s to id (-noprdb set)\n", username); } else { if ((status = krb_get_tf_realm(TKT_FILE, realm_of_user)) != KSUCCESS) { fprintf(stderr, "%s: Couldn't determine realm of user: %s)", progname, krb_err_txt[status]); return(AKLOG_KERBEROS); } if (strcmp(realm_of_user, realm_of_cell)) { strcat(username, "@"); strcat(username, realm_of_user); } if (dflag) printf("About to resolve name %s to id\n", username); if (!pr_Initialize (0, AFSDIR_CLIENT_ETC_DIRPATH, aserver.cell)) status = pr_SNameToId (username, &viceId); if (dflag) { if (status) printf("Error %d\n", status); else printf("Id %d\n", viceId); } /* * This is a crock, but it is Transarc's crock, so * we have to play along in order to get the * functionality. The way the afs id is stored is * as a string in the username field of the token. * Contrary to what you may think by looking at * the code for tokens, this hack (AFS ID %d) will * not work if you change %d to something else. */ if ((status == 0) && (viceId != ANONYMOUSID)) sprintf (username, "AFS ID %d", viceId); } if (dflag) printf("Set username to %s\n", username); /* Reset the "aclient" structure before we call ktc_SetToken. * This structure was first set by the ktc_GetToken call when * we were comparing whether identical tokens already existed. */ strncpy(aclient.name, username, MAXKTCNAMELEN - 1); strcpy(aclient.instance, ""); strncpy(aclient.cell, c.realm, MAXKTCREALMLEN - 1); if (dflag) printf("Getting tokens.\n"); if (status = ktc_SetToken(&aserver, &atoken, &aclient, 0)) { fprintf(stderr, "%s: unable to obtain tokens for cell %s (status: %d).\n", progname, cell_to_use, status); status = AKLOG_TOKEN; } return(status); }
int main(void) { struct ktc_principal oldServer[MAXCELLS], newServer[MAXCELLS]; struct ktc_principal oldClient[MAXCELLS], newClient[MAXCELLS]; struct ktc_token oldToken[MAXCELLS], newToken[MAXCELLS]; int cellCount, cellIndex; int i, code; #ifdef AFS_NT40_ENV /* Initialize winsock; required by NT pioctl() */ if (afs_winsockInit()) { printf("\nUnable to initialize winsock (required by NT pioctl()).\n"); exit(1); } #endif /* Get original tokens */ printf("\nFetching original tokens.\n"); cellIndex = 0; for (i = 0; i < MAXCELLS; i++) { /* fetch server principal */ code = ktc_ListTokens(cellIndex, &cellIndex, &oldServer[i]); if (code) { if (code == KTC_NOENT) { /* no more tokens */ break; } else { /* some error occured */ perror("ktc_ListTokens failed fetching original tokens"); exit(1); } } /* fetch token and client identity w.r.t. server */ code = ktc_GetToken(&oldServer[i], &oldToken[i], sizeof(struct ktc_token), &oldClient[i]); if (code) { /* some unexpected error occured */ perror("ktc_GetToken failed fetching original tokens"); exit(1); } } cellCount = i; if (cellCount == 0) { printf("Obtain one or more tokens prior to executing test.\n"); exit(0); } else if (cellCount == MAXCELLS) { printf("Only first %d tokens utilized by test; rest will be lost.\n", MAXCELLS); } for (i = 0; i < cellCount; i++) { printf("Token[%d]: server = %s@%s, client = %s@%s\n", i, oldServer[i].name, oldServer[i].cell, oldClient[i].name, oldClient[i].cell); } /* Forget original tokens */ printf("\nClearing original tokens and verifying disposal.\n"); code = ktc_ForgetAllTokens(); if (code) { perror("ktc_ForgetAllTokens failed on original tokens"); exit(1); } for (i = 0; i < cellCount; i++) { struct ktc_principal dummyPrincipal; struct ktc_token dummyToken; code = ktc_GetToken(&oldServer[i], &dummyToken, sizeof(struct ktc_token), &dummyPrincipal); if (code != KTC_NOENT) { printf("ktc_ForgetAllTokens did not eliminate all tokens.\n"); exit(1); } cellIndex = 0; code = ktc_ListTokens(cellIndex, &cellIndex, &dummyPrincipal); if (code != KTC_NOENT) { printf("ktc_ForgetAllTokens did not eliminate all tokens.\n"); exit(1); } } /* Reinstall tokens */ printf("\nReinstalling original tokens.\n"); for (i = 0; i < cellCount; i++) { code = ktc_SetToken(&oldServer[i], &oldToken[i], &oldClient[i], 0); if (code) { perror("ktc_SetToken failed reinstalling tokens"); exit(1); } } /* Get reinstalled tokens */ printf("\nFetching reinstalled tokens.\n"); cellIndex = 0; for (i = 0; i < MAXCELLS; i++) { /* fetch server principal */ code = ktc_ListTokens(cellIndex, &cellIndex, &newServer[i]); if (code) { if (code == KTC_NOENT) { /* no more tokens */ break; } else { /* some error occured */ perror("ktc_ListTokens failed fetching reinstalled tokens"); exit(1); } } /* fetch token and client identity w.r.t. server */ code = ktc_GetToken(&newServer[i], &newToken[i], sizeof(struct ktc_token), &newClient[i]); if (code) { /* some unexpected error occured */ perror("ktc_GetToken failed fetching reinstalled tokens"); exit(1); } } /* Verify content of reinstalled tokens */ printf("\nVerifying reinstalled tokens against original tokens.\n"); if (i != cellCount) { printf("Reinstalled token count does not match original count.\n"); exit(1); } for (i = 0; i < cellCount; i++) { int k, found; found = 0; for (k = 0; k < cellCount; k++) { if (SamePrincipal(&oldServer[i], &newServer[k]) && SamePrincipal(&oldClient[i], &newClient[k]) && SameToken(&oldToken[i], &newToken[k])) { /* found a matching token */ found = 1; break; } } if (!found) { printf("Reinstalled token does not match any original token.\n"); exit(1); } } /* Test passes */ printf("\nTest completed without error.\n"); return 0; }
afs_int32 ka_UserAuthenticateGeneral2(afs_int32 flags, char *name, char *instance, char *realm, char *password, char *smbname, Date lifetime, afs_int32 * password_expiresP, afs_int32 spare, char **reasonP) { int code; struct ktc_encryptionKey key1, key2; char *ticket = NULL; int ticketLen; struct ktc_encryptionKey sessionKey; long kvno; long expirationTime; char fullRealm[256]; char upperRealm[256]; struct servent *sp; int ttl; struct ktc_principal server; struct ktc_principal client; struct ktc_token token; if (instance == NULL) instance = ""; if (lifetime == 0) lifetime = MAXKTCTICKETLIFETIME; code = cm_SearchCellFile(realm, fullRealm, ka_AddHostProc, NULL); #ifdef AFS_AFSDB_ENV if (code) { code = cm_SearchCellByDNS(realm, fullRealm, &ttl, ka_AddHostProc, NULL); } #endif if (code) { *reasonP = "specified realm is unknown"; return (code); } strcpy(upperRealm, fullRealm); _strupr(upperRealm); /* encrypt password, both ways */ ka_StringToKey(password, upperRealm, &key1); des_string_to_key(password, &key2); /* set port number */ sp = getservbyname("kerberos", "udp"); if (sp) krb_set_port(ntohs(sp->s_port)); *reasonP = NULL; code = krb_get_in_tkt_ext(name, instance, upperRealm, "afs", "", lifetime, &key1, &key2, &ticket, &ticketLen, &sessionKey, &kvno, &expirationTime, reasonP); if (code && *reasonP == NULL) *reasonP = ka_MapKerberosError(code); if (code) return code; strcpy(server.name, "afs"); strcpy(server.instance, ""); strcpy(server.cell, fullRealm); /* Would like to use Vice ID's; using raw names for now. */ strcpy(client.name, name); strcpy(client.instance, instance); strcpy(client.cell, upperRealm); if (smbname) strcpy(client.smbname, smbname); token.startTime = 0; /* XXX */ token.endTime = expirationTime; token.sessionKey = sessionKey; token.kvno = (short)kvno; token.ticketLen = ticketLen; memcpy(token.ticket, ticket, ticketLen); code = ktc_SetToken(&server, &token, &client, (flags & KA_USERAUTH_AUTHENT_LOGON) ? AFS_SETTOK_LOGON : 0); if (code) { if (code == KTC_NOCM || code == KTC_NOCMRPC) *reasonP = "AFS service may not have started"; else if (code == KTC_RPC) *reasonP = "RPC failure in AFS gateway"; else if (code == KTC_NOCELL) *reasonP = "unknown cell"; else *reasonP = "unknown error"; } return code; }
int Leash_afs_klog( char *service, char *cell, char *realm, int LifeTime ) { /////#ifdef NO_AFS #if defined(NO_AFS) || defined(NO_KRB4) return(0); #else long rc; ////This is defined in krb.h: CREDENTIALS creds; KTEXT_ST ticket; struct ktc_principal aserver; struct ktc_principal aclient; char realm_of_user[REALM_SZ]; /* Kerberos realm of user */ char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */ char local_cell[MAXCELLCHARS+1]; char Dmycell[MAXCELLCHARS+1]; struct ktc_token atoken; struct ktc_token btoken; afsconf_cell ak_cellconfig; /* General information about the cell */ char RealmName[128]; char CellName[128]; char ServiceName[128]; DWORD CurrentState; char HostName[64]; BOOL try_krb5 = 0; int retry = 0; int len; #ifndef NO_KRB5 krb5_context context = 0; krb5_ccache _krb425_ccache = 0; krb5_creds increds; krb5_creds * k5creds = 0; krb5_error_code r; krb5_principal client_principal = 0; krb5_flags flags = 0; #endif /* NO_KRB5 */ if (!AfsAvailable || GetAfsStatus(&AfsOnLine) && !AfsOnLine) return(0); if ( !realm ) realm = ""; if ( !cell ) cell = ""; if ( !service ) service = ""; CurrentState = 0; memset(HostName, '\0', sizeof(HostName)); gethostname(HostName, sizeof(HostName)); if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) return(0); if (CurrentState != SERVICE_RUNNING) return(0); memset(RealmName, '\0', sizeof(RealmName)); memset(CellName, '\0', sizeof(CellName)); memset(ServiceName, '\0', sizeof(ServiceName)); memset(realm_of_user, '\0', sizeof(realm_of_user)); memset(realm_of_cell, '\0', sizeof(realm_of_cell)); memset(Dmycell, '\0', sizeof(Dmycell)); // NULL or empty cell returns information on local cell if (cell && cell[0]) strcpy(Dmycell, cell); rc = get_cellconfig(Dmycell, &ak_cellconfig, local_cell); if (rc && cell && cell[0]) { memset(Dmycell, '\0', sizeof(Dmycell)); rc = get_cellconfig(Dmycell, &ak_cellconfig, local_cell); } if (rc) return(rc); #ifndef NO_KRB5 if (!(r = Leash_krb5_initialize(&context, &_krb425_ccache))) { int i; memset((char *)&increds, 0, sizeof(increds)); (*pkrb5_cc_get_principal)(context, _krb425_ccache, &client_principal); i = krb5_princ_realm(context, client_principal)->length; if (i > REALM_SZ-1) i = REALM_SZ-1; strncpy(realm_of_user,krb5_princ_realm(context, client_principal)->data,i); realm_of_user[i] = 0; try_krb5 = 1; } #endif /* NO_KRB5 */ #ifndef NO_KRB4 if ( !try_krb5 || !realm_of_user[0] ) { if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS) { return(rc); } } #endif strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig)); if (strlen(service) == 0) strcpy(ServiceName, "afs"); else strcpy(ServiceName, service); if (strlen(cell) == 0) strcpy(CellName, local_cell); else strcpy(CellName, cell); if (strlen(realm) == 0) strcpy(RealmName, realm_of_cell); else strcpy(RealmName, realm); memset(&creds, '\0', sizeof(creds)); #ifndef NO_KRB5 if ( try_krb5 ) { /* First try Service/Cell@REALM */ if (r = (*pkrb5_build_principal)(context, &increds.server, strlen(RealmName), RealmName, ServiceName, CellName, 0)) { try_krb5 = 0; goto use_krb4; } increds.client = client_principal; increds.times.endtime = 0; /* Ask for DES since that is what V4 understands */ increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; #ifdef KRB5_TC_NOTICKET flags = 0; r = pkrb5_cc_set_flags(context, _krb425_ccache, flags); #endif if (r == 0) r = pkrb5_get_credentials(context, 0, _krb425_ccache, &increds, &k5creds); if (r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || r == KRB5KRB_ERR_GENERIC /* Heimdal */) { /* Next try Service@REALM */ pkrb5_free_principal(context, increds.server); r = pkrb5_build_principal(context, &increds.server, strlen(RealmName), RealmName, ServiceName, 0); if (r == 0) r = pkrb5_get_credentials(context, 0, _krb425_ccache, &increds, &k5creds); } pkrb5_free_principal(context, increds.server); pkrb5_free_principal(context, client_principal); #ifdef KRB5_TC_NOTICKET flags = KRB5_TC_NOTICKET; pkrb5_cc_set_flags(context, _krb425_ccache, flags); #endif (void) pkrb5_cc_close(context, _krb425_ccache); _krb425_ccache = 0; if (r || k5creds == 0) { pkrb5_free_context(context); try_krb5 = 0; goto use_krb4; } /* This code inserts the entire K5 ticket into the token * No need to perform a krb524 translation which is * commented out in the code below */ if ( use_krb524() || k5creds->ticket.length > MAXKTCTICKETLEN ) goto try_krb524d; memset(&aserver, '\0', sizeof(aserver)); strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1); strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1); memset(&atoken, '\0', sizeof(atoken)); atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5; atoken.startTime = k5creds->times.starttime; atoken.endTime = k5creds->times.endtime; memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length); atoken.ticketLen = k5creds->ticket.length; memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen); retry_gettoken5: rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient); if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) { if ( rc == KTC_NOCM && retry < 20 ) { Sleep(500); retry++; goto retry_gettoken5; } goto try_krb524d; } if (atoken.kvno == btoken.kvno && atoken.ticketLen == btoken.ticketLen && !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) && !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen)) { /* Success */ pkrb5_free_creds(context, k5creds); pkrb5_free_context(context); return(0); } // * Reset the "aclient" structure before we call ktc_SetToken. // * This structure was first set by the ktc_GetToken call when // * we were comparing whether identical tokens already existed. len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1); strncpy(aclient.name, k5creds->client->data[0].data, len); aclient.name[len] = '\0'; if ( k5creds->client->length > 1 ) { char * p; strcat(aclient.name, "."); p = aclient.name + strlen(aclient.name); len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1); strncpy(p, k5creds->client->data[1].data, len); p[len] = '\0'; } aclient.instance[0] = '\0'; strcpy(aclient.cell, realm_of_cell); len = min(k5creds->client->realm.length,strlen(realm_of_cell)); if ( strncmp(realm_of_cell, k5creds->client->realm.data, len) ) { char * p; strcat(aclient.name, "@"); p = aclient.name + strlen(aclient.name); len = min(k5creds->client->realm.length,MAXKTCNAMELEN - strlen(aclient.name) - 1); strncpy(p, k5creds->client->realm.data, len); p[len] = '\0'; } rc = ktc_SetToken(&aserver, &atoken, &aclient, 0); if (!rc) { /* Success */ pkrb5_free_creds(context, k5creds); pkrb5_free_context(context); return(0); } try_krb524d: /* This requires krb524d to be running with the KDC */ r = pkrb524_convert_creds_kdc(context, k5creds, &creds); pkrb5_free_creds(context, k5creds); pkrb5_free_context(context); if (r) { try_krb5 = 0; goto use_krb4; } rc = KSUCCESS; } else #endif /* NO_KRB5 */ { use_krb4: rc = KFAILURE; } if (rc != KSUCCESS) { return(rc); } memset(&aserver, '\0', sizeof(aserver)); strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1); strncpy(aserver.cell, CellName, MAXKTCNAMELEN - 1); memset(&atoken, '\0', sizeof(atoken)); atoken.kvno = creds.kvno; atoken.startTime = creds.issue_date; atoken.endTime = (*pkrb_life_to_time)(creds.issue_date,creds.lifetime); memcpy(&atoken.sessionKey, creds.session, 8); atoken.ticketLen = creds.ticket_st.length; memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen); if (!(rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient)) && atoken.kvno == btoken.kvno && atoken.ticketLen == btoken.ticketLen && !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) && !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen)) { return(0); } // * Reset the "aclient" structure before we call ktc_SetToken. // * This structure was first set by the ktc_GetToken call when // * we were comparing whether identical tokens already existed. strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1); aclient.name[MAXKTCNAMELEN - 1] = '\0'; if (creds.pinst[0]) { strncat(aclient.name, ".", MAXKTCNAMELEN - 1 - strlen(aclient.name)); aclient.name[MAXKTCNAMELEN - 1] = '\0'; strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1 - strlen(aclient.name)); aclient.name[MAXKTCNAMELEN - 1] = '\0'; } strcpy(aclient.instance, ""); if ( strcmp(realm_of_cell, creds.realm) ) { strncat(aclient.name, "@", MAXKTCNAMELEN - 1 - strlen(aclient.name)); aclient.name[MAXKTCNAMELEN - 1] = '\0'; strncat(aclient.name, creds.realm, MAXKTCNAMELEN - 1 - strlen(aclient.name)); aclient.name[MAXKTCNAMELEN - 1] = '\0'; } aclient.name[MAXKTCNAMELEN-1] = '\0'; strcpy(aclient.cell, CellName); // * NOTE: On WIN32, the order of SetToken params changed... // * to ktc_SetToken(&aserver, &aclient, &atoken, 0) // * from ktc_SetToken(&aserver, &atoken, &aclient, 0) on Unix... // * The afscompat ktc_SetToken provides the Unix order if (rc = ktc_SetToken(&aserver, &atoken, &aclient, 0)) { Leash_afs_error(rc, "ktc_SetToken()"); return(rc); } return(0); #endif }