Esempio n. 1
0
static void
get_princ(krb5_context context, krb5_principal *principal, const char *name)
{
    krb5_error_code ret;
    krb5_principal tmp;
    int parseflags = 0;
    char *user_realm;

    if (name == NULL) {
	krb5_ccache ccache;

	/* If credential cache provides a client principal, use that. */
	if (krb5_cc_default(context, &ccache) == 0) {
	    ret = krb5_cc_get_principal(context, ccache, principal);
	    krb5_cc_close(context, ccache);
	    if (ret == 0)
		return;
	}
    }

    user_realm = get_user_realm(context);

    if (name) {
	if (canonicalize_flag || enterprise_flag)
	    parseflags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE;

	parse_name_realm(context, name, parseflags, user_realm, &tmp);

	if (user_realm && krb5_principal_get_num_comp(context, tmp) > 1) {
	    /* Principal is instance qualified, reparse with default realm. */
	    krb5_free_principal(context, tmp);
	    parse_name_realm(context, name, parseflags, NULL, principal);
	} else {
	    *principal = tmp;
	}
    } else {
	get_default_principal(context, principal);
	if (user_realm)
	    set_princ_realm(context, *principal, user_realm);
    }

    if (user_realm)
	free(user_realm);
}
Esempio n. 2
0
/*
 * Given the krb5_principal from kadmind, convert it to the corresponding
 * principal in Active Directory.  This may involve removing ad_base_instance
 * and always involves changing the realm.  Returns a Kerberos error code.
 */
static krb5_error_code
get_ad_principal(kadm5_hook_modinfo *config, krb5_context ctx,
                 krb5_const_principal principal, krb5_principal *ad_principal)
{
    krb5_error_code code;
    int ncomp;

    /*
     * Set ad_principal to NULL to start.  We fall back on copy and realm
     * setting if we don't have to build it, and use whether it's NULL as a
     * flag.
     */
    *ad_principal = NULL;

    /* Get the number of components. */
    ncomp = krb5_principal_get_num_comp(ctx, principal);

    /* See if this is an ad_base_instance principal that needs a rewrite. */
    if (config->ad_base_instance != NULL && ncomp == 2) {
        const char *base, *instance;

        instance = krb5_principal_get_comp_string(ctx, principal, 1);
        if (strcmp(instance, config->ad_base_instance) == 0) {
            base = krb5_principal_get_comp_string(ctx, principal, 0);
            code = krb5_build_principal(ctx, ad_principal,
                                        strlen(config->ad_realm),
                                        config->ad_realm, base, (char *) 0);
            if (code != 0)
                return code;
        }
    }

    /* Otherwise, copy the principal and set the realm. */
    if (*ad_principal == NULL) {
        code = krb5_copy_principal(ctx, principal, ad_principal);
        if (code != 0)
            return code;
        krb5_principal_set_realm(ctx, *ad_principal, config->ad_realm);
    }
    return 0;
}
Esempio n. 3
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;
    int flags = 0;
    char * smbname = getenv("AFS_SMBNAME");

    /* 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;

            msg = krb5_get_error_message(context, status);
            fprintf(stderr, "%s: Couldn't determine realm of user: %s\n",
                    progname, msg);
            krb5_free_error_message(context, msg);
            status = AKLOG_KERBEROS;
            goto done;
        }

        if ( strchr(name,'.') != NULL && !accept_dotted_usernames()) {
            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) {
            msg = krb5_get_error_message(context, 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)
            krb5_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;
        const char *un;

        un = krb5_principal_get_comp_string(context, v5cred->client, 0);
        strncpy(username, un, MAXKTCNAMELEN - 1);
        username[MAXKTCNAMELEN - 1] = '\0';

        if ( krb5_principal_get_num_comp(context, v5cred->client) > 1 ) {
            strcat(username, ".");
            p = username + strlen(username);
            len = (unsigned int)(MAXKTCNAMELEN - strlen(username) - 1);
            strncpy(p, krb5_principal_get_comp_string(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;
	if (tkt_DeriveDesKey(v5cred->session.keytype,
			     v5cred->session.keyvalue.data,
			     v5cred->session.keyvalue.length, &atoken.sessionKey)) {
	    status = AKLOG_MISC;
	    goto done;
	}
        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 &&
        !smbname &&
        !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) {
        strncpy(aclient.cell,
                krb5_principal_get_realm(context, v5cred->client), MAXKTCNAMELEN - 1);
        aclient.cell[MAXKTCNAMELEN - 1] = '\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 ( smbname ) {
        if (dflag)
            printf("Setting tokens for %s.\n", smbname);

        strncpy(aclient.smbname, smbname, MAXKTCNAMELEN - 1);
        aclient.smbname[MAXKTCNAMELEN - 1] = '\0';
        flags = AFS_SETTOK_LOGON;
    } else {
        if (dflag)
            printf("Setting tokens.\n");
    }

    if (status = ktc_SetToken(&aserver, &atoken, &aclient, flags))
    {
        afs_com_err(progname, status,
                     "while setting token 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);
}