예제 #1
0
파일: kssl.c 프로젝트: jmhodges/libssl
/*  Replaces krb5_build_principal_ext(), with varargs length == 2 (svc, host),
**  because I dont't know how to stub varargs.
**  Returns krb5_error_code == ENOMEM on alloc error, otherwise
**  passes back newly constructed principal, which should be freed by caller.
*/
krb5_error_code
kssl_build_principal_2(
	/* UPDATE */	krb5_context	context,
	/* OUT    */	krb5_principal	*princ,
	/* IN     */	int rlen,  const char *realm,
	/* IN	  */	int slen,  const char *svc,
	/* IN	  */	int hlen,  const char *host)
{
	krb5_data		*p_data = NULL;
	krb5_principal		new_p = NULL;
        char			*new_r = NULL;

	if ((p_data = (krb5_data *)calloc(2, sizeof(krb5_data))) == NULL ||
	    (new_p = (krb5_principal)calloc(1, sizeof(krb5_principal_data)))
	    == NULL)
		goto err;
	new_p->length = 2;
	new_p->data = p_data;

	if ((new_r = calloc(1, rlen + 1)) == NULL)
		goto err;
	memcpy(new_r, realm, rlen);
	krb5_princ_set_realm_length(context, new_p, rlen);
	krb5_princ_set_realm_data(context, new_p, new_r);

	if ((new_p->data[0].data = calloc(1, slen + 1)) == NULL)
		goto err;
	memcpy(new_p->data[0].data, svc, slen);
	new_p->data[0].length = slen;

	if ((new_p->data[1].data = calloc(1, hlen + 1)) == NULL)
		goto err;
	memcpy(new_p->data[1].data, host, hlen);
	new_p->data[1].length = hlen;
	
	krb5_princ_type(context, new_p) = KRB5_NT_UNKNOWN;
	*princ = new_p;
	return 0;

err:
	if (new_p && new_p[0].data)
		free(new_p[0].data);
	if (new_p && new_p[1].data)
		free(new_p[1].data);
	if (new_p)
		free(new_p);
	if (new_r)
		free(new_r);
	return ENOMEM;
}
예제 #2
0
/*
 * Check whether the request satisfies the conditions for generating a referral
 * TGT.  The caller checks whether the hostname component looks like a FQDN.
 */
static krb5_boolean
is_referral_req(kdc_realm_t *kdc_active_realm, krb5_kdc_req *request)
{
    krb5_boolean ret = FALSE;
    char *stype = NULL;
    char *ref_services = kdc_active_realm->realm_host_based_services;
    char *nonref_services = kdc_active_realm->realm_no_host_referral;

    if (!(request->kdc_options & KDC_OPT_CANONICALIZE))
        return FALSE;

    if (request->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY)
        return FALSE;

    if (krb5_princ_size(kdc_context, request->server) != 2)
        return FALSE;

    stype = data2string(krb5_princ_component(kdc_context, request->server, 0));
    if (stype == NULL)
        return FALSE;
    switch (krb5_princ_type(kdc_context, request->server)) {
    case KRB5_NT_UNKNOWN:
        /* Allow referrals for NT-UNKNOWN principals, if configured. */
        if (kdc_active_realm->realm_host_based_services != NULL) {
            if (!krb5_match_config_pattern(ref_services, stype) &&
                !krb5_match_config_pattern(ref_services, KRB5_CONF_ASTERISK))
                goto cleanup;
        } else
            goto cleanup;
        /* FALLTHROUGH */
    case KRB5_NT_SRV_HST:
    case KRB5_NT_SRV_INST:
        /* Deny referrals for specific service types, if configured. */
        if (kdc_active_realm->realm_no_host_referral != NULL) {
            if (krb5_match_config_pattern(nonref_services, stype))
                goto cleanup;
            if (krb5_match_config_pattern(nonref_services, KRB5_CONF_ASTERISK))
                goto cleanup;
        }
        ret = TRUE;
        break;
    default:
        goto cleanup;
    }
cleanup:
    free(stype);
    return ret;
}
예제 #3
0
/*
 * Check whether the request satisfies the conditions for generating a referral
 * TGT.  The caller checks whether the hostname component looks like a FQDN.
 */
static krb5_boolean
is_referral_req(kdc_realm_t *kdc_active_realm, krb5_kdc_req *request)
{
    krb5_boolean ret = FALSE;
    char *stype = NULL;
    char *hostbased = kdc_active_realm->realm_hostbased;
    char *no_referral = kdc_active_realm->realm_no_referral;

    if (!(request->kdc_options & KDC_OPT_CANONICALIZE))
        return FALSE;

    if (request->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY)
        return FALSE;

    if (krb5_princ_size(kdc_context, request->server) != 2)
        return FALSE;

    stype = data2string(krb5_princ_component(kdc_context, request->server, 0));
    if (stype == NULL)
        return FALSE;
    switch (krb5_princ_type(kdc_context, request->server)) {
    case KRB5_NT_UNKNOWN:
        /* Allow referrals for NT-UNKNOWN principals, if configured. */
        if (!in_list(hostbased, stype) && !in_list(hostbased, "*"))
            goto cleanup;
        /* FALLTHROUGH */
    case KRB5_NT_SRV_HST:
    case KRB5_NT_SRV_INST:
        /* Deny referrals for specific service types, if configured. */
        if (in_list(no_referral, stype) || in_list(no_referral, "*"))
            goto cleanup;
        ret = TRUE;
        break;
    default:
        goto cleanup;
    }
cleanup:
    free(stype);
    return ret;
}
예제 #4
0
/* Get a TGT for use at the remote host */
krb5_error_code KRB5_CALLCONV
krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, char *rhost, krb5_principal client, krb5_principal server, krb5_ccache cc, int forwardable, krb5_data *outbuf)
                         
                                   
                
                          
                          
                   
                          /* Should forwarded TGT also be forwardable? */
                      
{
    krb5_replay_data replaydata;
    krb5_data * scratch = 0;
    krb5_address **addrs = NULL;
    krb5_error_code retval;
    krb5_creds creds, tgt;
    krb5_creds *pcreds;
    krb5_flags kdcoptions;
    int close_cc = 0;
    int free_rhost = 0;
    krb5_enctype enctype = 0;
    krb5_keyblock *session_key;
    krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes;

    memset((char *)&creds, 0, sizeof(creds));
    memset((char *)&tgt, 0, sizeof(creds));

    if (cc == 0) {
      if ((retval = krb5int_cc_default(context, &cc)))
	goto errout;
      close_cc = 1;
    }
    retval = krb5_auth_con_getkey (context, auth_context, &session_key);
    if (retval)
      goto errout;
    if (session_key) {
	enctype = session_key->enctype;
	krb5_free_keyblock (context, session_key);
	session_key = NULL;
    } else if (server) { /* must server be non-NULL when rhost is given? */
	/* Try getting credentials to see what the remote side supports.
	   Not bulletproof, just a heuristic.  */
	krb5_creds in, *out = 0;
	memset (&in, 0, sizeof(in));

	retval = krb5_copy_principal (context, server, &in.server);
	if (retval)
	    goto punt;
	retval = krb5_copy_principal (context, client, &in.client);
	if (retval)
	    goto punt;
	retval = krb5_get_credentials (context, 0, cc, &in, &out);
	if (retval)
	    goto punt;
	/* Got the credentials.  Okay, now record the enctype and
	   throw them away.  */
	enctype = out->keyblock.enctype;
	krb5_free_creds (context, out);
    punt:
	krb5_free_cred_contents (context, &in);
    }

    if ((retval = krb5_copy_principal(context, client, &creds.client)))
	goto errout;
    
    if ((retval = krb5_build_principal_ext(context, &creds.server,
					   client->realm.length,
					   client->realm.data,
					   KRB5_TGS_NAME_SIZE,
					   KRB5_TGS_NAME,
					   client->realm.length,
					   client->realm.data,
					   0)))
	goto errout;
	
    /* fetch tgt directly from cache */
    context->use_conf_ktypes = 1;
    retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_SUPPORTED_KTYPES,
				    &creds, &tgt);
    context->use_conf_ktypes = old_use_conf_ktypes;
    if (retval)
	goto errout;

    /* tgt->client must be equal to creds.client */
    if (!krb5_principal_compare(context, tgt.client, creds.client)) {	
        /* Solaris Kerberos */
        char *r_name = NULL;
	char *t_name = NULL;
	krb5_error_code r_err, t_err;
	t_err = krb5_unparse_name(context, tgt.client, &t_name);
	r_err = krb5_unparse_name(context, creds.client, &r_name);
	krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
			    dgettext(TEXT_DOMAIN,
				    "Requested principal and ticket don't match:  Requested principal is '%s' and TGT principal is '%s'"),
			    r_err ? "unknown" : r_name,
			    t_err ? "unknown" : t_name);
	if (r_name)
	    krb5_free_unparsed_name(context, r_name);
	if (t_name)
	    krb5_free_unparsed_name(context, t_name);
	retval = KRB5_PRINC_NOMATCH;
	goto errout;
    }

    if (!tgt.ticket.length) {
	retval = KRB5_NO_TKT_SUPPLIED;
	goto errout;
    }
    
    if (tgt.addresses && *tgt.addresses) {
      if (rhost == NULL) {
	if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) {
retval = KRB5_FWD_BAD_PRINCIPAL;
 goto errout;
	}

	if (krb5_princ_size(context, server) < 2){
	  retval = KRB5_CC_BADNAME;
	  goto errout;
	}
	
	rhost = malloc(server->data[1].length+1);
	if (!rhost) {
	  retval = ENOMEM;
	  goto errout;
	}
	free_rhost = 1;
	/* Solaris Kerberos */
	(void) memcpy(rhost, server->data[1].data, server->data[1].length);
	rhost[server->data[1].length] = '\0';
      }

	retval = krb5_os_hostaddr(context, rhost, &addrs);
	if (retval)
	    goto errout;
    }
    
    creds.keyblock.enctype = enctype;
    creds.times = tgt.times;
    creds.times.starttime = 0;
    kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED;

    if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */
      kdcoptions &= ~(KDC_OPT_FORWARDABLE);

    if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
					addrs, &creds, &pcreds))) {
	if (enctype) {
	    creds.keyblock.enctype = 0;
	    if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
						addrs, &creds, &pcreds))) 
		goto errout;
	}
	else goto errout;
    }
    retval = krb5_mk_1cred(context, auth_context, pcreds,
                           &scratch, &replaydata);
    krb5_free_creds(context, pcreds);

    /*
     * Solaris Kerberos: changed this logic from the MIT 1.2.1 version to be
     * more robust.
     */
    if (scratch) {
	if (retval)
	    krb5_free_data(context, scratch);
	else {                                 
	    *outbuf = *scratch;
	    krb5_xfree(scratch);
	}                      
    }
        
errout:
    if (addrs)
	krb5_free_addresses(context, addrs);
    /* Solaris Kerberos */
    if (close_cc)
	(void) krb5_cc_close(context, cc);
    if (free_rhost)
	free(rhost);
    krb5_free_cred_contents(context, &creds);
    krb5_free_cred_contents(context, &tgt);
    return retval;
}
예제 #5
0
static krb5_int32
prep_reprocess_req(krb5_kdc_req *request, krb5_principal *krbtgt_princ)
{
    krb5_error_code retval = KRB5KRB_AP_ERR_BADMATCH;
    size_t len = 0;
    char **realms, **cpp, *temp_buf=NULL;
    krb5_data *comp1 = NULL, *comp2 = NULL;
    char *comp1_str = NULL;

    /* By now we know that server principal name is unknown.
     * If CANONICALIZE flag is set in the request
     * If req is not U2U authn. req
     * the requested server princ. has exactly two components
     * either
     *      the name type is NT-SRV-HST
     *      or name type is NT-UNKNOWN and
     *         the 1st component is listed in conf file under host_based_services
     * the 1st component is not in a list in conf under "no_host_referral"
     * the 2d component looks like fully-qualified domain name (FQDN)
     * If all of these conditions are satisfied - try mapping the FQDN and
     * re-process the request as if client had asked for cross-realm TGT.
     */
    if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) &&
        !isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) &&
        krb5_princ_size(kdc_context, request->server) == 2) {

        comp1 = krb5_princ_component(kdc_context, request->server, 0);
        comp2 = krb5_princ_component(kdc_context, request->server, 1);

        comp1_str = calloc(1,comp1->length+1);
        if (!comp1_str) {
            retval = ENOMEM;
            goto cleanup;
         }
        strlcpy(comp1_str,comp1->data,comp1->length+1);

        if ((krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_HST ||
            (krb5_princ_type(kdc_context, request->server) == KRB5_NT_UNKNOWN &&
            kdc_active_realm->realm_host_based_services != NULL &&
            (krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, comp1_str) == TRUE ||
             krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, KRB5_CONF_ASTERISK) == TRUE))) &&
            (kdc_active_realm->realm_no_host_referral == NULL ||
            (krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, KRB5_CONF_ASTERISK) == FALSE &&
             krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, comp1_str) == FALSE))) {

            for (len=0; len < comp2->length; len++) {
                 if (comp2->data[len] == '.') break;
            }
            if (len == comp2->length)
                goto cleanup;
            temp_buf = calloc(1, comp2->length+1);
            if (!temp_buf){
                retval = ENOMEM;
                goto cleanup;
            }
            strlcpy(temp_buf, comp2->data,comp2->length+1);
            retval = krb5int_get_domain_realm_mapping(kdc_context, temp_buf, &realms);
            free(temp_buf);
            if (retval) {
                /* no match found */
                kdc_err(kdc_context, retval, 0);
                goto cleanup;
            }
            if (realms == 0) {
                retval = KRB5KRB_AP_ERR_BADMATCH;
                goto cleanup;
            }
            if (realms[0] == 0) {
                free(realms);
                retval = KRB5KRB_AP_ERR_BADMATCH;
                goto cleanup;
            }
            /* Modify request.
             * Construct cross-realm tgt :  krbtgt/REMOTE_REALM@LOCAL_REALM
             * and use it as a principal in this req.
             */
            retval = krb5_build_principal(kdc_context, krbtgt_princ,
                                          (*request->server).realm.length,
                                          (*request->server).realm.data,
                                          "krbtgt", realms[0], (char *)0);
            for (cpp = realms; *cpp; cpp++)
                   free(*cpp);
        }
    }
cleanup:
    free(comp1_str);
    return retval;
}
예제 #6
0
/**
 * @brief
 * 		Get a TGT for use at the remote host.
 *
 * @param[in]	context	-	The Kerberos context.
 * @param[in]	auth_context	- Authentication context
 * @param[in]	client	-	Principal to be copied
 * @param[in]	server	-	Server of type krb5_principal
 * @param[in]	cc	-	Credential cache handle
 * @param[out]	outbuf	-	Replay cache data (NULL if not needed)
 *
 * @return	krb5_error_code
 * @retval	0	- success
 * @retval	!=0	- failure
 */
static
krb5_error_code
fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, krb5_principal client, krb5_principal server, krb5_ccache cc, krb5_data outbuf)
{
	krb5_replay_data	replaydata;
	krb5_data		*scratch = 0;
	krb5_address		**addrs = 0;
	krb5_flags		kdcoptions;
	krb5_error_code		retval;
	krb5_creds		creds, tgt;
	krb5_creds		*pcreds;
	int			free_rhost = 0;
	char			*rhost;

	memset((char *)&creds, 0, sizeof(creds));
	memset((char *)&tgt, 0, sizeof(creds));

	if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST)
		return KRB5_FWD_BAD_PRINCIPAL;

	if (krb5_princ_size(context, server) < 2)
		return KRB5_CC_BADNAME;

	rhost = malloc(server->data[1].length+1);
	if (!rhost)
		return ENOMEM;
	free_rhost = 1;
	memcpy(rhost, server->data[1].data, server->data[1].length);
	rhost[server->data[1].length] = '\0';

	retval = krb5_os_hostaddr(context, rhost, &addrs);
	if (retval)
		goto errout;

	if ((retval = krb5_copy_principal(context, client, &creds.client)))
		goto errout;

	if ((retval = krb5_build_principal_ext(context, &creds.server,
		client->realm.length,
		client->realm.data,
		KRB5_TGS_NAME_SIZE,
		KRB5_TGS_NAME,
		client->realm.length,
		client->realm.data,
		0)))
		goto errout;

	/* fetch tgt directly from cache */
	retval = 	krb5_cc_retrieve_cred(context, cc, KRB5_TC_SUPPORTED_KTYPES,
		&creds, &tgt);
	if (retval)
		goto errout;

	/* tgt->client must be equal to creds.client */
	if (!krb5_principal_compare(context, tgt.client, creds.client)) {
		retval = KRB5_PRINC_NOMATCH;
		goto errout;
	}
	if (!tgt.ticket.length) {
		retval = KRB5_NO_TKT_SUPPLIED;
		goto errout;
	}

	kdcoptions = flags2options(tgt.ticket_flags)|
		KDC_OPT_FORWARDED;

	if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
		addrs, &creds, &pcreds)))
		goto errout;

	retval = krb5_mk_1cred(context, auth_context, pcreds,
		&scratch, &replaydata);
	krb5_free_creds(context, pcreds);

	if (retval) {
		if (scratch)
			krb5_free_data(context, scratch);
	}
	else {
		*outbuf = *scratch;
		free(scratch);
	}

errout:
	if (addrs)
		krb5_free_addresses(context, addrs);
	if (free_rhost)
		free(rhost);
	krb5_free_cred_contents(context, &creds);
	krb5_free_cred_contents(context, &tgt);

	return retval;
}
예제 #7
0
/*
 * May the fleas of a thousand camels infest the ISO, they who think
 * that arbitrarily large multi-component names are a Good Thing.....
 */
static krb5_error_code
k5_parse_name(krb5_context context, const char *name,
	      int flags, krb5_principal *nprincipal)
{
	register const char	*cp;
	register char	*q;
	register int	i,c,size;
	int		components = 0;
	const char	*parsed_realm = NULL;
	int		fcompsize[FCOMPNUM];
	unsigned int	realmsize = 0;
	char		*default_realm = NULL;
	int		default_realm_size = 0;
	char		*tmpdata;
	krb5_principal	principal;
	krb5_error_code retval;
	unsigned int	enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE);
	int		first_at;

	/*
	 * Pass 1.  Find out how many components there are to the name,
	 * and get string sizes for the first FCOMPNUM components. For
	 * enterprise principal names (UPNs), there is only a single
	 * component.
	 */
	size = 0;
	for (i=0,cp = name, first_at = 1; (c = *cp); cp++) {
		if (c == QUOTECHAR) {
			cp++;
			if (!(c = *cp))
				/*
			 	 * QUOTECHAR can't be at the last
			 	 * character of the name!
			 	 */
				return(KRB5_PARSE_MALFORMED);
			size++;
			continue;
		} else if (c == COMPONENT_SEP && !enterprise) {
			if (parsed_realm)
				/*
				 * Shouldn't see a component separator
				 * after we've parsed out the realm name!
				 */
				return(KRB5_PARSE_MALFORMED);
			if (i < FCOMPNUM) {
				fcompsize[i] = size;
			}
			size = 0;
			i++;
		} else if (c == REALM_SEP && (!enterprise || !first_at)) {
			if (parsed_realm)
				/*
				 * Multiple realm separaters
				 * not allowed; zero-length realms are.
				 */
				return(KRB5_PARSE_MALFORMED);
			parsed_realm = cp + 1;
			if (i < FCOMPNUM) {
				fcompsize[i] = size;
			}
			size = 0;
		} else {
			if (c == REALM_SEP && enterprise && first_at)
				first_at = 0;

			size++;
		}
	}
	if (parsed_realm != NULL)
		realmsize = size;
	else if (i < FCOMPNUM) 
		fcompsize[i] = size;
	components = i + 1;
	/*
	 * Now, we allocate the principal structure and all of its
	 * component pieces
	 */
	principal = (krb5_principal)malloc(sizeof(krb5_principal_data));
	if (principal == NULL) {
	    return(ENOMEM);
	}
	principal->data = (krb5_data *) malloc(sizeof(krb5_data) * components);
	if (principal->data == NULL) {
	    krb5_xfree((char *)principal);
	    return ENOMEM;
	}
	principal->length = components;

	/*
	 * If a realm was not found, then use the default realm, unless
	 * KRB5_PRINCIPAL_PARSE_NO_REALM was specified in which case the
	 * realm will be empty.
	 */
	if (!parsed_realm) {
	    if (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM) {
		krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
				       "Principal %s is missing required realm", name);
		krb5_xfree(principal->data);
		krb5_xfree(principal);
		return KRB5_PARSE_MALFORMED;
	    }
	    if (!default_realm && (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) == 0) {
		retval = krb5_get_default_realm(context, &default_realm);
		if (retval) {
		    krb5_xfree(principal->data);
		    krb5_xfree((char *)principal);
		    return(retval);
		}
		default_realm_size = strlen(default_realm);
	    }
	    realmsize = default_realm_size;
	} else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) {
	    krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
				  "Principal %s has realm present", name);
	    krb5_xfree(principal->data);
	    krb5_xfree(principal);
	    return KRB5_PARSE_MALFORMED;
	}

	/*
	 * Pass 2.  Happens only if there were more than FCOMPNUM
	 * component; if this happens, someone should be shot
	 * immediately.  Nevertheless, we will attempt to handle said
	 * case..... <martyred sigh>
	 */
	if (components >= FCOMPNUM) {
		size = 0;
		parsed_realm = NULL;
		for (i=0,cp = name; (c = *cp); cp++) {
			if (c == QUOTECHAR) {
				cp++;
				size++;
			} else if (c == COMPONENT_SEP) {
				if (krb5_princ_size(context, principal) > i)
					krb5_princ_component(context, principal, i)->length = size;
				size = 0;
				i++;
			} else if (c == REALM_SEP) {
				if (krb5_princ_size(context, principal) > i)
					krb5_princ_component(context, principal, i)->length = size;
				size = 0;
				parsed_realm = cp+1;
			} else
				size++;
		}
		if (parsed_realm)
			krb5_princ_realm(context, principal)->length = size;
		else
			if (krb5_princ_size(context, principal) > i)
				krb5_princ_component(context, principal, i)->length = size;
		if (i + 1 != components) {
#if !defined(_WIN32)
		    fprintf(stderr,
			    "Programming error in krb5_parse_name!");
#endif
		    assert(i + 1 == components);
		    abort();
		}
	} else {
		/*
		 * If there were fewer than FCOMPSIZE components (the
		 * usual case), then just copy the sizes to the
		 * principal structure
		 */
		for (i=0; i < components; i++)
			krb5_princ_component(context, principal, i)->length = fcompsize[i];
	}
	/*	
	 * Now, we need to allocate the space for the strings themselves.....
	 */
	tmpdata = malloc(realmsize + 1);
	if (tmpdata == 0) {
		krb5_xfree(principal->data);
		krb5_xfree(principal);
		krb5_xfree(default_realm);
		return ENOMEM;
	}
	krb5_princ_set_realm_length(context, principal, realmsize);
	krb5_princ_set_realm_data(context, principal, tmpdata);
	for (i=0; i < components; i++) {
		char *tmpdata2 =
		  malloc(krb5_princ_component(context, principal, i)->length + 1);
		if (tmpdata2 == NULL) {
			for (i--; i >= 0; i--)
				krb5_xfree(krb5_princ_component(context, principal, i)->data);
			krb5_xfree(krb5_princ_realm(context, principal)->data);
			krb5_xfree(principal->data);
			krb5_xfree(principal);
			krb5_xfree(default_realm);
			return(ENOMEM);
		}
		krb5_princ_component(context, principal, i)->data = tmpdata2;
		krb5_princ_component(context, principal, i)->magic = KV5M_DATA;
	}
	
	/*
	 * Pass 3.  Now we go through the string a *third* time, this
	 * time filling in the krb5_principal structure which we just
	 * allocated.
	 */
	q = krb5_princ_component(context, principal, 0)->data;
	for (i=0,cp = name, first_at = 1; (c = *cp); cp++) {
		if (c == QUOTECHAR) {
			cp++;
			switch (c = *cp) {
			case 'n':
				*q++ = '\n';
				break;
			case 't':
				*q++ = '\t';
				break;
			case 'b':
				*q++ = '\b';
				break;
			case '0':
				*q++ = '\0';
				break;
			default:
				*q++ = c;
				break;
			}
		} else if (c == COMPONENT_SEP && !enterprise) {
			i++;
			*q++ = '\0';
			q = krb5_princ_component(context, principal, i)->data;
		} else if (c == REALM_SEP && (!enterprise || !first_at)) {
			i++;
			*q++ = '\0';
			q = krb5_princ_realm(context, principal)->data;
		} else {
			if (c == REALM_SEP && enterprise && first_at)
				first_at = 0;

			*q++ = c;
		}
	}
	*q++ = '\0';
	if (!parsed_realm) {
		if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM)
			(krb5_princ_realm(context, principal)->data)[0] = '\0';
		else
			strlcpy(krb5_princ_realm(context, principal)->data, default_realm, realmsize+1);
	}
	/*
	 * Alright, we're done.  Now stuff a pointer to this monstrosity
	 * into the return variable, and let's get out of here.
	 */
	if (enterprise)
		krb5_princ_type(context, principal) = KRB5_NT_ENTERPRISE_PRINCIPAL;
	else
		krb5_princ_type(context, principal) = KRB5_NT_PRINCIPAL;
	principal->magic = KV5M_PRINCIPAL;
	principal->realm.magic = KV5M_DATA;
	*nprincipal = principal;

	if (default_realm != NULL)
		krb5_xfree(default_realm);

	return(0);
}
예제 #8
0
krb5_error_code KRB5_CALLCONV
krb5_sname_to_principal(krb5_context context, const char *hostname, const char *sname, krb5_int32 type, krb5_principal *ret_princ)
{
    char **hrealms, *realm, *remote_host;
    krb5_error_code retval;
    register char *cp;
    char localname[MAXHOSTNAMELEN];

#ifdef DEBUG_REFERRALS
    printf("krb5_sname_to_principal(host=%s, sname=%s, type=%d)\n",hostname,sname,type);
    printf("      name types: 0=unknown, 3=srv_host\n");
#endif

    if ((type == KRB5_NT_UNKNOWN) ||
            (type == KRB5_NT_SRV_HST)) {

        /* if hostname is NULL, use local hostname */
        if (! hostname) {
            if (gethostname(localname, MAXHOSTNAMELEN))
                return SOCKET_ERRNO;
            hostname = localname;
        }

        /* if sname is NULL, use "host" */
        if (! sname)
            sname = "host";

        /* copy the hostname into non-volatile storage */

        if (type == KRB5_NT_SRV_HST) {
            struct addrinfo *ai, hints;
            int err;
            char hnamebuf[NI_MAXHOST];

            /* Note that the old code would accept numeric addresses,
               and if the gethostbyaddr step could convert them to
               real hostnames, you could actually get reasonable
               results.  If the mapping failed, you'd get dotted
               triples as realm names.  *sigh*

               The latter has been fixed in hst_realm.c, but we should
               keep supporting numeric addresses if they do have
               hostnames associated.  */

            memset(&hints, 0, sizeof(hints));
            hints.ai_family = AF_INET;
            hints.ai_flags = AI_CANONNAME;
try_getaddrinfo_again:
            err = getaddrinfo(hostname, 0, &hints, &ai);
            if (err) {
#ifdef DEBUG_REFERRALS
                printf("sname_to_princ: probably punting due to bad hostname of %s\n",hostname);
#endif
                if (hints.ai_family == AF_INET) {
                    /* Just in case it's an IPv6-only name.  */
                    hints.ai_family = 0;
                    goto try_getaddrinfo_again;
                }
                return KRB5_ERR_BAD_HOSTNAME;
            }
            remote_host = strdup(ai->ai_canonname ? ai->ai_canonname : hostname);
            if (!remote_host) {
                freeaddrinfo(ai);
                return ENOMEM;
            }

            if (maybe_use_reverse_dns(context, DEFAULT_RDNS_LOOKUP)) {
                /*
                 * Do a reverse resolution to get the full name, just in
                 * case there's some funny business going on.  If there
                 * isn't an in-addr record, give up.
                 */
                /* XXX: This is *so* bogus.  There are several cases where
                   this won't get us the canonical name of the host, but
                   this is what we've trained people to expect.  We'll
                   probably fix it at some point, but let's try to
                   preserve the current behavior and only shake things up
                   once when it comes time to fix this lossage.  */
                err = getnameinfo(ai->ai_addr, ai->ai_addrlen,
                                  hnamebuf, sizeof(hnamebuf), 0, 0, NI_NAMEREQD);
                freeaddrinfo(ai);
                if (err == 0) {
                    free(remote_host);
                    remote_host = strdup(hnamebuf);
                    if (!remote_host)
                        return ENOMEM;
                }
            } else
                freeaddrinfo(ai);
        } else { /* type == KRB5_NT_UNKNOWN */
            remote_host = strdup(hostname);
        }
        if (!remote_host)
            return ENOMEM;
#ifdef DEBUG_REFERRALS
        printf("sname_to_princ: hostname <%s> after rdns processing\n",remote_host);
#endif

        if (type == KRB5_NT_SRV_HST)
            for (cp = remote_host; *cp; cp++)
                if (isupper((unsigned char) (*cp)))
                    *cp = tolower((unsigned char) (*cp));

        /*
         * Windows NT5's broken resolver gratuitously tacks on a
         * trailing period to the hostname (at least it does in
         * Beta2).  Find and remove it.
         */
        if (remote_host[0]) {
            cp = remote_host + strlen(remote_host)-1;
            if (*cp == '.')
                *cp = 0;
        }


        if ((retval = krb5_get_host_realm(context, remote_host, &hrealms))) {
            free(remote_host);
            return retval;
        }

#ifdef DEBUG_REFERRALS
        printf("sname_to_princ:  realm <%s> after krb5_get_host_realm\n",hrealms[0]);
#endif

        if (!hrealms[0]) {
            free(remote_host);
            free(hrealms);
            return KRB5_ERR_HOST_REALM_UNKNOWN;
        }
        realm = hrealms[0];

        retval = krb5_build_principal(context, ret_princ, strlen(realm),
                                      realm, sname, remote_host,
                                      (char *)0);
        if (retval == 0)
            krb5_princ_type(context, *ret_princ) = type;

#ifdef DEBUG_REFERRALS
        printf("krb5_sname_to_principal returning\n");
        printf("realm: <%s>, sname: <%s>, remote_host: <%s>\n",
               realm,sname,remote_host);
        krb5int_dbgref_dump_principal("krb5_sname_to_principal",*ret_princ);
#endif

        free(remote_host);

        krb5_free_host_realm(context, hrealms);
        return retval;
    } else {
        return KRB5_SNAME_UNSUPP_NAMETYPE;
    }
}
예제 #9
0
파일: kssl.c 프로젝트: jmhodges/libssl
/*  Given d2i_-decoded asn1ticket, allocate and return a new krb5_ticket.
**  Return Kerberos error code and kssl_err struct on error.
**  Allocates krb5_ticket and krb5_principal; caller should free these.
**
**	20010410	VRS	Implemented krb5_decode_ticket() as
**				old_krb5_decode_ticket(). Missing from MIT1.0.6.
**	20010615	VRS 	Re-cast as openssl/asn1 d2i_*() functions.
**				Re-used some of the old krb5_decode_ticket()
**				code here.  This tkt should alloc/free just
**				like the real thing.
*/
static krb5_error_code
kssl_TKT2tkt(
	/* IN     */	krb5_context	krb5context,
	/* IN     */	KRB5_TKTBODY	*asn1ticket,
	/* OUT    */	krb5_ticket	**krb5ticket,
	/* OUT    */	KSSL_ERR *kssl_err  )
{
        krb5_error_code			krb5rc = KRB5KRB_ERR_GENERIC;
	krb5_ticket 			*new5ticket = NULL;
	ASN1_GENERALSTRING		*gstr_svc, *gstr_host;

	*krb5ticket = NULL;

	if (asn1ticket == NULL || asn1ticket->realm == NULL ||
	    asn1ticket->sname == NULL ||
	    sk_ASN1_GENERALSTRING_num(asn1ticket->sname->namestring) < 2) {
		(void) snprintf(kssl_err->text, KSSL_ERR_MAX,
		    "Null field in asn1ticket.\n");
		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
		return KRB5KRB_ERR_GENERIC;
	}

	if ((new5ticket =
	    (krb5_ticket *)calloc(1, sizeof(krb5_ticket))) == NULL) {
		(void) snprintf(kssl_err->text, KSSL_ERR_MAX,
		    "Unable to allocate new krb5_ticket.\n");
		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
		return ENOMEM; /*  or  KRB5KRB_ERR_GENERIC; */
	}

	gstr_svc = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 0);
	gstr_host = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 1);

	if ((krb5rc = kssl_build_principal_2(krb5context, &new5ticket->server,
	    asn1ticket->realm->length, (char *)asn1ticket->realm->data,
	    gstr_svc->length, (char *)gstr_svc->data, gstr_host->length,
	    (char *)gstr_host->data)) != 0) {
		free(new5ticket);
		(void) snprintf(kssl_err->text, KSSL_ERR_MAX,
		    "Error building ticket server principal.\n");
		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
		return krb5rc; /*  or  KRB5KRB_ERR_GENERIC; */
	}

	krb5_princ_type(krb5context, new5ticket->server) =
	    asn1ticket->sname->nametype->data[0];
	new5ticket->enc_part.enctype = asn1ticket->encdata->etype->data[0];
	new5ticket->enc_part.kvno = asn1ticket->encdata->kvno->data[0];
	new5ticket->enc_part.ciphertext.length =
	    asn1ticket->encdata->cipher->length;
	if ((new5ticket->enc_part.ciphertext.data =
	    calloc(1, asn1ticket->encdata->cipher->length)) == NULL) {
		free(new5ticket);
		(void) snprintf(kssl_err->text, KSSL_ERR_MAX,
		    "Error allocating cipher in krb5ticket.\n");
		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
		return KRB5KRB_ERR_GENERIC;
	} else {
		memcpy(new5ticket->enc_part.ciphertext.data,
		asn1ticket->encdata->cipher->data,
		asn1ticket->encdata->cipher->length);
	}

	*krb5ticket = new5ticket;
	return 0;
}
예제 #10
0
파일: do_as_req.c 프로젝트: pexip/os-krb5
/*ARGSUSED*/
void
process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
               const krb5_fulladdr *from, verto_ctx *vctx,
               loop_respond_fn respond, void *arg)
{
    krb5_error_code errcode;
    krb5_timestamp rtime;
    unsigned int s_flags = 0;
    krb5_principal_data client_princ;
    krb5_data encoded_req_body;
    krb5_enctype useenctype;
    struct as_req_state *state;

    state = malloc(sizeof(*state));
    if (!state) {
        (*respond)(arg, ENOMEM, NULL);
        return;
    }
    state->session_key.contents = 0;
    state->enc_tkt_reply.authorization_data = NULL;
    state->reply.padata = 0;
    memset(&state->reply, 0, sizeof(state->reply));
    state->respond = respond;
    state->arg = arg;
    state->ticket_reply.enc_part.ciphertext.data = 0;
    state->server_keyblock.contents = NULL;
    state->client_keyblock.contents = NULL;
    state->reply_encpart.enc_padata = 0;
    state->client = NULL;
    state->server = NULL;
    state->request = request;
    state->e_data = NULL;
    state->typed_e_data = FALSE;
    state->authtime = 0;
    state->c_flags = 0;
    state->req_pkt = req_pkt;
    state->rstate = NULL;
    state->sname = 0;
    state->cname = 0;
    state->pa_context = NULL;
    state->from = from;
    memset(&state->rock, 0, sizeof(state->rock));

#if APPLE_PKINIT
    asReqDebug("process_as_req top realm %s name %s\n",
               request->client->realm.data, request->client->data->data);
#endif /* APPLE_PKINIT */

    if (state->request->msg_type != KRB5_AS_REQ) {
        state->status = "msg_type mismatch";
        errcode = KRB5_BADMSGTYPE;
        goto errout;
    }
    errcode = kdc_make_rstate(&state->rstate);
    if (errcode != 0) {
        state->status = "constructing state";
        goto errout;
    }
    if (fetch_asn1_field((unsigned char *) req_pkt->data,
                         1, 4, &encoded_req_body) != 0) {
        errcode = ASN1_BAD_ID;
        state->status = "Finding req_body";
        goto errout;
    }
    errcode = kdc_find_fast(&state->request, &encoded_req_body, NULL, NULL,
                            state->rstate, &state->inner_body);
    if (errcode) {
        state->status = "error decoding FAST";
        goto errout;
    }
    if (state->inner_body == NULL) {
        /* Not a FAST request; copy the encoded request body. */
        errcode = krb5_copy_data(kdc_context, &encoded_req_body,
                                 &state->inner_body);
        if (errcode) {
            state->status = "storing req body";
            goto errout;
        }
    }
    state->rock.request = state->request;
    state->rock.inner_body = state->inner_body;
    state->rock.rstate = state->rstate;
    state->rock.vctx = vctx;
    if (!state->request->client) {
        state->status = "NULL_CLIENT";
        errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
        goto errout;
    }
    if ((errcode = krb5_unparse_name(kdc_context,
                                     state->request->client,
                                     &state->cname))) {
        state->status = "UNPARSING_CLIENT";
        goto errout;
    }
    limit_string(state->cname);
    if (!state->request->server) {
        state->status = "NULL_SERVER";
        errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
        goto errout;
    }
    if ((errcode = krb5_unparse_name(kdc_context,
                                     state->request->server,
                                     &state->sname))) {
        state->status = "UNPARSING_SERVER";
        goto errout;
    }
    limit_string(state->sname);

    /*
     * We set KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY as a hint
     * to the backend to return naming information in lieu
     * of cross realm TGS entries.
     */
    setflag(state->c_flags, KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY);
    /*
     * Note that according to the referrals draft we should
     * always canonicalize enterprise principal names.
     */
    if (isflagset(state->request->kdc_options, KDC_OPT_CANONICALIZE) ||
        state->request->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
        setflag(state->c_flags, KRB5_KDB_FLAG_CANONICALIZE);
        setflag(state->c_flags, KRB5_KDB_FLAG_ALIAS_OK);
    }
    if (include_pac_p(kdc_context, state->request)) {
        setflag(state->c_flags, KRB5_KDB_FLAG_INCLUDE_PAC);
    }
    errcode = krb5_db_get_principal(kdc_context, state->request->client,
                                    state->c_flags, &state->client);
    if (errcode == KRB5_KDB_NOENTRY) {
        state->status = "CLIENT_NOT_FOUND";
        if (vague_errors)
            errcode = KRB5KRB_ERR_GENERIC;
        else
            errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
        goto errout;
    } else if (errcode) {
        state->status = "LOOKING_UP_CLIENT";
        goto errout;
    }
    state->rock.client = state->client;

    /*
     * If the backend returned a principal that is not in the local
     * realm, then we need to refer the client to that realm.
     */
    if (!is_local_principal(state->client->princ)) {
        /* Entry is a referral to another realm */
        state->status = "REFERRAL";
        errcode = KRB5KDC_ERR_WRONG_REALM;
        goto errout;
    }

#if 0
    /*
     * Turn off canonicalization if client is marked DES only
     * (unless enterprise principal name was requested)
     */
    if (isflagset(client->attributes, KRB5_KDB_NON_MS_PRINCIPAL) &&
        krb5_princ_type(kdc_context,
                        request->client) != KRB5_NT_ENTERPRISE_PRINCIPAL) {
        clear(c_flags, KRB5_KDB_FLAG_CANONICALIZE);
    }
#endif

    s_flags = 0;
    setflag(s_flags, KRB5_KDB_FLAG_ALIAS_OK);
    if (isflagset(state->request->kdc_options, KDC_OPT_CANONICALIZE)) {
        setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE);
    }
    errcode = krb5_db_get_principal(kdc_context, state->request->server,
                                    s_flags, &state->server);
    if (errcode == KRB5_KDB_NOENTRY) {
        state->status = "SERVER_NOT_FOUND";
        errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
        goto errout;
    } else if (errcode) {
        state->status = "LOOKING_UP_SERVER";
        goto errout;
    }

    if ((errcode = krb5_timeofday(kdc_context, &state->kdc_time))) {
        state->status = "TIMEOFDAY";
        goto errout;
    }
    state->authtime = state->kdc_time; /* for audit_as_request() */

    if ((errcode = validate_as_request(state->request, *state->client,
                                       *state->server, state->kdc_time,
                                       &state->status, &state->e_data))) {
        if (!state->status)
            state->status = "UNKNOWN_REASON";
        errcode += ERROR_TABLE_BASE_krb5;
        goto errout;
    }

    /*
     * Select the keytype for the ticket session key.
     */
    if ((useenctype = select_session_keytype(kdc_context, state->server,
                                             state->request->nktypes,
                                             state->request->ktype)) == 0) {
        /* unsupported ktype */
        state->status = "BAD_ENCRYPTION_TYPE";
        errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
        goto errout;
    }

    if ((errcode = krb5_c_make_random_key(kdc_context, useenctype,
                                          &state->session_key))) {
        state->status = "RANDOM_KEY_FAILED";
        goto errout;
    }

    /*
     * Canonicalization is only effective if we are issuing a TGT
     * (the intention is to allow support for Windows "short" realm
     * aliases, nothing more).
     */
    if (isflagset(s_flags, KRB5_KDB_FLAG_CANONICALIZE) &&
        krb5_is_tgs_principal(state->request->server) &&
        krb5_is_tgs_principal(state->server->princ)) {
        state->ticket_reply.server = state->server->princ;
    } else {
        state->ticket_reply.server = state->request->server;
    }

    state->enc_tkt_reply.flags = 0;
    state->enc_tkt_reply.times.authtime = state->authtime;

    setflag(state->enc_tkt_reply.flags, TKT_FLG_INITIAL);
    setflag(state->enc_tkt_reply.flags, TKT_FLG_ENC_PA_REP);

    /*
     * It should be noted that local policy may affect the
     * processing of any of these flags.  For example, some
     * realms may refuse to issue renewable tickets
     */

    if (isflagset(state->request->kdc_options, KDC_OPT_FORWARDABLE))
        setflag(state->enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);

    if (isflagset(state->request->kdc_options, KDC_OPT_PROXIABLE))
        setflag(state->enc_tkt_reply.flags, TKT_FLG_PROXIABLE);

    if (isflagset(state->request->kdc_options, KDC_OPT_ALLOW_POSTDATE))
        setflag(state->enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE);

    state->enc_tkt_reply.session = &state->session_key;
    if (isflagset(state->c_flags, KRB5_KDB_FLAG_CANONICALIZE)) {
        client_princ = *(state->client->princ);
    } else {
        client_princ = *(state->request->client);
        /* The realm is always canonicalized */
        client_princ.realm = state->client->princ->realm;
    }
    state->enc_tkt_reply.client = &client_princ;
    state->enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
    state->enc_tkt_reply.transited.tr_contents = empty_string;

    if (isflagset(state->request->kdc_options, KDC_OPT_POSTDATED)) {
        setflag(state->enc_tkt_reply.flags, TKT_FLG_POSTDATED);
        setflag(state->enc_tkt_reply.flags, TKT_FLG_INVALID);
        state->enc_tkt_reply.times.starttime = state->request->from;
    } else
        state->enc_tkt_reply.times.starttime = state->kdc_time;

    kdc_get_ticket_endtime(kdc_context, state->enc_tkt_reply.times.starttime,
                           kdc_infinity, state->request->till, state->client,
                           state->server, &state->enc_tkt_reply.times.endtime);

    if (isflagset(state->request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
        !isflagset(state->client->attributes, KRB5_KDB_DISALLOW_RENEWABLE) &&
        (state->enc_tkt_reply.times.endtime < state->request->till)) {

        /* we set the RENEWABLE option for later processing */

        setflag(state->request->kdc_options, KDC_OPT_RENEWABLE);
        state->request->rtime = state->request->till;
    }
    rtime = (state->request->rtime == 0) ? kdc_infinity :
        state->request->rtime;

    if (isflagset(state->request->kdc_options, KDC_OPT_RENEWABLE)) {
        /*
         * XXX Should we squelch the output renew_till to be no
         * earlier than the endtime of the ticket?
         */
        setflag(state->enc_tkt_reply.flags, TKT_FLG_RENEWABLE);
        state->enc_tkt_reply.times.renew_till =
            min(rtime, state->enc_tkt_reply.times.starttime +
                min(state->client->max_renewable_life,
                    min(state->server->max_renewable_life,
                        max_renewable_life_for_realm)));
    } else
        state->enc_tkt_reply.times.renew_till = 0; /* XXX */

    /*
     * starttime is optional, and treated as authtime if not present.
     * so we can nuke it if it matches
     */
    if (state->enc_tkt_reply.times.starttime ==
        state->enc_tkt_reply.times.authtime)
        state->enc_tkt_reply.times.starttime = 0;

    state->enc_tkt_reply.caddrs = state->request->addresses;
    state->enc_tkt_reply.authorization_data = 0;

    /* If anonymous requests are being used, adjust the realm of the client
     * principal. */
    if (isflagset(state->request->kdc_options, KDC_OPT_REQUEST_ANONYMOUS)) {
        if (!krb5_principal_compare_any_realm(kdc_context,
                                              state->request->client,
                                              krb5_anonymous_principal())) {
            errcode = KRB5KDC_ERR_BADOPTION;
            state->status = "Anonymous requested but anonymous "
                "principal not used.";
            goto errout;
        }
        setflag(state->enc_tkt_reply.flags, TKT_FLG_ANONYMOUS);
        krb5_free_principal(kdc_context, state->request->client);
        errcode = krb5_copy_principal(kdc_context, krb5_anonymous_principal(),
                                      &state->request->client);
        if (errcode) {
            state->status = "Copying anonymous principal";
            goto errout;
        }
        state->enc_tkt_reply.client = state->request->client;
        setflag(state->client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH);
    }

    /*
     * Check the preauthentication if it is there.
     */
    if (state->request->padata) {
        check_padata(kdc_context, &state->rock, state->req_pkt,
                     state->request, &state->enc_tkt_reply, &state->pa_context,
                     &state->e_data, &state->typed_e_data, finish_preauth,
                     state);
    } else
        finish_preauth(state, 0);
    return;

errout:
    finish_process_as_req(state, errcode);
}
예제 #11
0
파일: kvno.c 프로젝트: OPSF/uClinux
static void do_v5_kvno (int count, char *names[],
                        char * ccachestr, char *etypestr, char *keytab_name,
                        char *sname, int canon, int unknown)
{
    krb5_error_code ret;
    int i, errors;
    krb5_enctype etype;
    krb5_ccache ccache;
    krb5_principal me;
    krb5_creds in_creds, *out_creds;
    krb5_ticket *ticket;
    char *princ;
    krb5_keytab keytab = NULL;

    ret = krb5_init_context(&context);
    if (ret) {
        com_err(prog, ret, "while initializing krb5 library");
        exit(1);
    }

    if (etypestr) {
        ret = krb5_string_to_enctype(etypestr, &etype);
        if (ret) {
            com_err(prog, ret, "while converting etype");
            exit(1);
        }
    } else {
        etype = 0;
    }

    if (ccachestr)
        ret = krb5_cc_resolve(context, ccachestr, &ccache);
    else
        ret = krb5_cc_default(context, &ccache);
    if (ret) {
        com_err(prog, ret, "while opening ccache");
        exit(1);
    }

    if (keytab_name) {
        ret = krb5_kt_resolve(context, keytab_name, &keytab);
        if (ret) {
            com_err(prog, ret, "resolving keytab %s", keytab_name);
            exit(1);
        }
    }

    ret = krb5_cc_get_principal(context, ccache, &me);
    if (ret) {
        com_err(prog, ret, "while getting client principal name");
        exit(1);
    }

    errors = 0;

    for (i = 0; i < count; i++) {
        memset(&in_creds, 0, sizeof(in_creds));

        in_creds.client = me;

        if (sname != NULL) {
            ret = krb5_sname_to_principal(context, names[i],
                                          sname, KRB5_NT_SRV_HST,
                                          &in_creds.server);
        } else {
            ret = krb5_parse_name(context, names[i], &in_creds.server);
        }
        if (ret) {
            if (!quiet)
                com_err(prog, ret, "while parsing principal name %s", names[i]);
            errors++;
            continue;
        }
        if (unknown == 1) {
            krb5_princ_type(context, in_creds.server) = KRB5_NT_UNKNOWN;
        }

        ret = krb5_unparse_name(context, in_creds.server, &princ);
        if (ret) {
            com_err(prog, ret,
                    "while formatting parsed principal name for '%s'",
                    names[i]);
            errors++;
            continue;
        }

        in_creds.keyblock.enctype = etype;

        ret = krb5_get_credentials(context, canon ? KRB5_GC_CANONICALIZE : 0,
                                   ccache, &in_creds, &out_creds);

        krb5_free_principal(context, in_creds.server);

        if (ret) {
            com_err(prog, ret, "while getting credentials for %s", princ);

            krb5_free_unparsed_name(context, princ);

            errors++;
            continue;
        }

        /* we need a native ticket */
        ret = krb5_decode_ticket(&out_creds->ticket, &ticket);
        if (ret) {
            com_err(prog, ret, "while decoding ticket for %s", princ);
            krb5_free_creds(context, out_creds);
            krb5_free_unparsed_name(context, princ);

            errors++;
            continue;
        }

        if (keytab) {
            ret = krb5_server_decrypt_ticket_keytab(context, keytab, ticket);
            if (ret) {
                if (!quiet)
                    printf("%s: kvno = %d, keytab entry invalid", princ, ticket->enc_part.kvno);
                com_err(prog, ret, "while decrypting ticket for %s", princ);
                krb5_free_ticket(context, ticket);
                krb5_free_creds(context, out_creds);
                krb5_free_unparsed_name(context, princ);

                errors++;
                continue;
            }
            if (!quiet)
                printf("%s: kvno = %d, keytab entry valid\n", princ, ticket->enc_part.kvno);
        } else {
            if (!quiet)
                printf("%s: kvno = %d\n", princ, ticket->enc_part.kvno);
        }

        krb5_free_creds(context, out_creds);
        krb5_free_unparsed_name(context, princ);
    }

    if (keytab)
        krb5_kt_close(context, keytab);
    krb5_free_principal(context, me);
    krb5_cc_close(context, ccache);
    krb5_free_context(context);

    if (errors)
        exit(1);

    exit(0);
}