Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
/*
 * 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;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
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);
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
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 *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);
}
Exemplo n.º 10
0
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 */
}
Exemplo n.º 11
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(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);
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
0
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
}