Esempio n. 1
0
krb5_error_code KRB5_CALLCONV
krb5_copy_creds(krb5_context context, const krb5_creds *incred, krb5_creds **outcred)
{
    krb5_creds *tempcred;
    krb5_error_code retval;
    krb5_data *scratch;

    if (!(tempcred = (krb5_creds *)malloc(sizeof(*tempcred))))
	return ENOMEM;

    *tempcred = *incred;
    retval = krb5_copy_principal(context, incred->client, &tempcred->client);
    if (retval)
	goto cleanlast;
    retval = krb5_copy_principal(context, incred->server, &tempcred->server);
    if (retval)
	goto cleanclient;
    retval = krb5_copy_keyblock_contents(context, &incred->keyblock,
					 &tempcred->keyblock);
    if (retval)
	goto cleanserver;
    retval = krb5_copy_addresses(context, incred->addresses, &tempcred->addresses);
    if (retval)
	goto cleanblock;
    retval = krb5_copy_data(context, &incred->ticket, &scratch);
    if (retval)
	goto cleanaddrs;
    tempcred->ticket = *scratch;
    krb5_xfree(scratch);
    retval = krb5_copy_data(context, &incred->second_ticket, &scratch);
    if (retval)
	goto cleanticket;

    tempcred->second_ticket = *scratch;
    krb5_xfree(scratch);

    retval = krb5_copy_authdata(context, incred->authdata,&tempcred->authdata);
    if (retval)
        goto clearticket;

    *outcred = tempcred;
    return 0;

 clearticket:    
    memset(tempcred->ticket.data,0,tempcred->ticket.length);
 cleanticket:
    free(tempcred->ticket.data);
 cleanaddrs:
    krb5_free_addresses(context, tempcred->addresses);
 cleanblock:
    krb5_xfree(tempcred->keyblock.contents);
 cleanserver:
    krb5_free_principal(context, tempcred->server);
 cleanclient:
    krb5_free_principal(context, tempcred->client);
 cleanlast:
    krb5_xfree(tempcred);
    return retval;
}
Esempio n. 2
0
static krb5_error_code
prof_locate_server (krb5_context context, const krb5_data *realm,
		    char ***hostlist,
		    enum locate_service_type svc)
{
    const char	*realm_srv_names[4];
    char **hl, *host, *profname;
    krb5_error_code code;
    int i, j, count;

    *hostlist = NULL;  /* default - indicate no KDCs found */

    switch (svc) {
    case locate_service_kdc:
	profname = "kdc";
	break;
    case locate_service_master_kdc:
        profname = "master_kdc";
	break;
    case locate_service_kadmin:
	profname = "admin_server";
	break;
    case locate_service_krb524:
	profname = "krb524_server";
	break;
    case locate_service_kpasswd:
	profname = "kpasswd_server";
	break;
    default:
	return EINVAL;
    }

    if ((host = malloc(realm->length + 1)) == NULL) 
	return ENOMEM;

    (void) strncpy(host, realm->data, realm->length);
    host[realm->length] = '\0';
    hl = 0;

    realm_srv_names[0] = "realms";
    realm_srv_names[1] = host;
    realm_srv_names[2] = profname;
    realm_srv_names[3] = 0;

    code = profile_get_values(context->profile, realm_srv_names, &hl);
    if (code) {
	Tprintf ("config file lookup failed: %s\n",
		 error_message(code));
        if (code == PROF_NO_SECTION || code == PROF_NO_RELATION)
	    code = KRB5_REALM_UNKNOWN;
 	krb5_xfree(host);
  	return code;
     }
    krb5_xfree(host);

    *hostlist = hl;

    return 0;
}
Esempio n. 3
0
static krb5_error_code
krb5_compat_recvauth(krb5_context context,
		    krb5_auth_context *auth_context,
		    krb5_pointer fdp,	/* IN */
		    krb5_principal server,	/* IN */
		    krb5_int32 flags,	/* IN */
		    krb5_keytab keytab,	/* IN */
		    krb5_ticket **ticket, /* OUT */
		    krb5_int32 *auth_sys, /* OUT */
		    krb5_data *version)   /* OUT */
{
	krb5_int32 vlen;
	char	*buf;
	int	len, length;
	krb5_int32	retval;
	int		fd = *((int *)fdp);

	if ((retval = krb5_net_read(context, fd, (char *)&vlen, 4)) != 4)
		return ((retval < 0) ? errno : ECONNABORTED);

	/*
	 * Assume that we're talking to a V5 recvauth; read in the
	 * the version string, and make sure it matches.
	 */
	len = (int)ntohl(vlen);

	if (len < 0 || len > 255)
		return (KRB5_SENDAUTH_BADAUTHVERS);

	buf = malloc(len);
	if (buf == NULL)
		return (ENOMEM);

	length = krb5_net_read(context, fd, buf, len);
	if (len != length) {
		krb5_xfree(buf);
		return ((len < 0) ? errno : ECONNABORTED);
	}

	if (strcmp(buf, KRB_V5_SENDAUTH_VERS) != 0) {
		krb5_xfree(buf);
		return (KRB5_SENDAUTH_BADAUTHVERS);
	}
	krb5_xfree(buf);

	*auth_sys = KRB5_RECVAUTH_V5;

	retval = krb5_recvauth_version(context, auth_context, fdp,
				    server, flags | KRB5_RECVAUTH_SKIP_VERSION,
				    keytab, ticket, version);

	return (retval);
}
Esempio n. 4
0
void sess_finalize(struct rekey_session *sess) 
{
  OM_uint32 min;
  if (sess->state == REKEY_SESSION_SENDING)
    prtmsg("warning: session closed before reply sent");
  if (sess->ssl) {
    SSL_shutdown(sess->ssl);
    SSL_free(sess->ssl);
  }
  if (sess->kadm_handle)
    kadm5_destroy(sess->kadm_handle);
  if (sess->realm) {
#if defined(HAVE_KRB5_REALM)
    krb5_xfree(sess->realm);
#else
    krb5_free_default_realm(sess->kctx, sess->realm);
#endif
  }
  if (sess->princ)
    krb5_free_principal(sess->kctx, sess->princ);
  if (sess->kctx)
    krb5_free_context(sess->kctx);
  if (sess->gctx)
    (void)gss_delete_sec_context(&min, &sess->gctx, GSS_C_NO_BUFFER);
  if (sess->name)
    (void)gss_release_name(&min, &sess->name);
  if (sess->dbh)
    sqlite3_close(sess->dbh);
  free(sess->hostname);
  free(sess->plain_name);
  memset(&sess, 0, sizeof(sess));
}
Esempio n. 5
0
krb5_error_code KRB5_CALLCONV
krb5_ktsrvtab_close(krb5_context context, krb5_keytab id)
  /*
   * This routine is responsible for freeing all memory allocated 
   * for this keytab.  There are no system resources that need
   * to be freed nor are there any open files.
   *
   * This routine should undo anything done by krb5_ktsrvtab_resolve().
   */
{
    krb5_xfree(KTFILENAME(id));
    krb5_xfree(id->data);
    id->ops = 0;
    krb5_xfree(id);
    return (0);
}
Esempio n. 6
0
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
krb5_copy_data(krb5_context context, const krb5_data *indata, krb5_data **outdata)
{
    krb5_data *tempdata;

    if (!indata) {
	*outdata = 0;
	return 0;
    }
    
    if (!(tempdata = (krb5_data *)malloc(sizeof(*tempdata))))
	return ENOMEM;

    tempdata->length = indata->length;
    if (tempdata->length) {
	if (!(tempdata->data = malloc(tempdata->length))) {
	    krb5_xfree(tempdata);
	    return ENOMEM;
	}
	memcpy((char *)tempdata->data, (char *)indata->data, tempdata->length);
    } else
	tempdata->data = 0;
    tempdata->magic = KV5M_DATA;
    *outdata = tempdata;
    return 0;
}
Esempio n. 7
0
/*
 * krb5_principal_externalize()	- Externalize the krb5_principal.
 */
static krb5_error_code
krb5_principal_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
{
    krb5_error_code	kret;
    krb5_principal	principal;
    size_t		required;
    krb5_octet		*bp;
    size_t		remain;
    char		*fname;

    required = 0;
    bp = *buffer;
    remain = *lenremain;
    kret = EINVAL;
    if ((principal = (krb5_principal) arg)) {
	kret = ENOMEM;
	if (!krb5_principal_size(kcontext, arg, &required) &&
	    (required <= remain)) {
	    if (!(kret = krb5_unparse_name(kcontext, principal, &fname))) {

		(void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain);
		(void) krb5_ser_pack_int32((krb5_int32) strlen(fname),
					   &bp, &remain);
		(void) krb5_ser_pack_bytes((krb5_octet *) fname,
					   strlen(fname), &bp, &remain);
		(void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain);
		*buffer = bp;
		*lenremain = remain;

		krb5_xfree(fname);
	    }
	}
    }
    return(kret);
}
Esempio n. 8
0
krb5_error_code KRB5_CALLCONV
krb5_rc_dfl_resolve(krb5_context context, krb5_rcache id, char *name)
{
    struct dfl_data *t = 0;
    krb5_error_code retval;

    /* allocate id? no */
    if (!(t = (struct dfl_data *) malloc(sizeof(struct dfl_data))))
	return KRB5_RC_MALLOC;
    id->data = (krb5_pointer) t;
    memset(t, 0, sizeof(struct dfl_data));
    if (name) {
	t->name = malloc(strlen(name)+1);
	if (!t->name) {
	    retval = KRB5_RC_MALLOC;
	    goto cleanup;
	}
	strcpy(t->name, name);
    } else
	t->name = 0;
    t->numhits = t->nummisses = 0;
    t->hsize = HASHSIZE; /* no need to store---it's memory-only */
    t->h = (struct authlist **) malloc(t->hsize*sizeof(struct authlist *));
    if (!t->h) {
	retval = KRB5_RC_MALLOC;
	goto cleanup;
    }
    memset(t->h, 0, t->hsize*sizeof(struct authlist *));
    t->a = (struct authlist *) 0;
#ifndef NOIOSTUFF
    t->d.fd = -1;
#endif
    t->recovering = 0;
    return 0;

cleanup:
    if (t) {
	if (t->name)
	    krb5_xfree(t->name);
	if (t->h)
	    krb5_xfree(t->h);
	krb5_xfree(t);
    }
    return retval;
}
Esempio n. 9
0
void
krb5_free_realm_tree(krb5_context context, krb5_principal *realms)
{
    register krb5_principal *nrealms = realms;
    while (*nrealms) {
	krb5_free_principal(context, *nrealms);
	nrealms++;
    }
    krb5_xfree(realms);
}
Esempio n. 10
0
void
krb5_ldap_free_krbcontainer_params(krb5_ldap_krbcontainer_params *cparams)
{
    if (cparams == NULL)
        return;

    if (cparams->policyreference)
        krb5_xfree(cparams->policyreference);

    if (cparams->parent)
        krb5_xfree(cparams->parent);

    if (cparams->DN)
        krb5_xfree(cparams->DN);

    krb5_xfree(cparams);

    return;
}
Esempio n. 11
0
static krb5_error_code
kcm_get_cache_next(krb5_context context, krb5_cc_cursor cursor, const krb5_cc_ops *ops, krb5_ccache *id)
{
    krb5_error_code ret;
    krb5_kcm_cursor c = KCMCURSOR(cursor);
    krb5_storage *request, *response;
    krb5_data response_data;
    ssize_t sret;
    char *name;

    *id = NULL;

 again:

    if (c->offset >= c->length)
	return KRB5_CC_END;

    ret = krb5_kcm_storage_request(context, KCM_OP_GET_CACHE_BY_UUID, &request);
    if (ret)
	return ret;

    sret = krb5_storage_write(request,
			      &c->uuids[c->offset],
			      sizeof(c->uuids[c->offset]));
    c->offset++;
    if (sret != sizeof(c->uuids[c->offset])) {
	krb5_storage_free(request);
	krb5_clear_error_message(context);
	return ENOMEM;
    }

    ret = krb5_kcm_call(context, request, &response, &response_data);
    krb5_storage_free(request);
    if (ret == KRB5_FCC_NOFILE) {
	/* cache no longer exists, try next */
	goto again;
    } else if (ret)
	return ret;

    ret = krb5_ret_stringz(response, &name);
    krb5_storage_free(response);
    krb5_data_free(&response_data);
    if (ret)
	return ret;

    ret = _krb5_cc_allocate(context, ops, id);
    if (ret == 0)
	ret = kcm_alloc(context, name, id);
    krb5_xfree(name);

    return ret;
}
Esempio n. 12
0
static CFStringRef
CFStringCreateFromPrincipal(krb5_context context, krb5_principal principal)
{
    CFStringRef str;
    char *p;
    
    if (krb5_unparse_name(context, principal, &p) != 0)
	return NULL;
    
    str = CFStringCreateWithCString(NULL, p, kCFStringEncodingUTF8);
    krb5_xfree(p);
    
    return str;
}
Esempio n. 13
0
/*ARGSUSED*/
static krb5_error_code
krb5_get_as_key_keytab(
    krb5_context context,
    krb5_principal client,
    krb5_enctype etype,
    krb5_prompter_fct prompter,
    void *prompter_data,
    krb5_data *salt,
    krb5_data *params,
    krb5_keyblock *as_key,
    void *gak_data)
{
    krb5_keytab keytab = (krb5_keytab) gak_data;
    krb5_error_code ret;
    krb5_keytab_entry kt_ent;
    krb5_keyblock *kt_key;

    /* if there's already a key of the correct etype, we're done.
       if the etype is wrong, free the existing key, and make
       a new one. */

    if (as_key->length) {
	if (as_key->enctype == etype)
	    return(0);

	krb5_free_keyblock_contents(context, as_key);
	as_key->length = 0;
    }

    if (!krb5_c_valid_enctype(etype))
	return(KRB5_PROG_ETYPE_NOSUPP);

    /* Solaris Kerberos */
    if ((ret = krb5_kt_get_entry(context, keytab, client,
				 0, /* don't have vno available */
				 etype, &kt_ent)) != NULL)
	return(ret);

    ret = krb5_copy_keyblock(context, &kt_ent.key, &kt_key);

    /* again, krb5's memory management is lame... */

    *as_key = *kt_key;
    krb5_xfree(kt_key);

    (void) krb5_kt_free_entry(context, &kt_ent);

    return(ret);
}
Esempio n. 14
0
static krb5_error_code KRB5_CALLCONV
krb5_ktsrvtab_resolve(krb5_context context, const char *name, krb5_keytab *id)
{
    krb5_ktsrvtab_data *data;
    FILE *fp;

    /* Make sure we can open the srvtab file for reading. */
    fp = fopen(name, "r");
    if (!fp)
	return(errno);
    fclose(fp);

    if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL)
	return(ENOMEM);
    
    (*id)->ops = &krb5_kts_ops;
    data = (krb5_ktsrvtab_data *)malloc(sizeof(krb5_ktsrvtab_data));
    if (data == NULL) {
	krb5_xfree(*id);
	return(ENOMEM);
    }

    data->name = (char *)malloc(strlen(name) + 1);
    if (data->name == NULL) {
	krb5_xfree(data);
	krb5_xfree(*id);
	return(ENOMEM);
    }

    (void) strcpy(data->name, name);
    data->openf = 0;

    (*id)->data = (krb5_pointer)data;
    (*id)->magic = KV5M_KEYTAB;
    return(0);
}
Esempio n. 15
0
void
kssl_krb5_free_data_contents(krb5_context context, krb5_data *data)
{
#ifdef KRB5_HEIMDAL
	data->length = 0;
	if (data->data)
		free(data->data);
#elif defined(KRB5_MIT_OLD11)
	if (data->data)  {
		krb5_xfree(data->data);
		data->data = 0;
	}
#else
	krb5_free_data_contents(NULL, data);
#endif
}
Esempio n. 16
0
std::string KRB5Principal::name()
{
    char *principal_string;
    krb5_error_code ret = krb5_unparse_name(g_context.get(), m_princ, &principal_string);
    if (ret) {
        throw KRB5Exception("krb5_unparse_name", ret);
    }

    std::string result(principal_string);

#ifdef HEIMDAL
    krb5_xfree(principal_string);
#else
    krb5_free_unparsed_name(g_context.get(), principal_string);
#endif

    return result;
}
Esempio n. 17
0
krb5_error_code
krb5int_copy_data_contents(krb5_context context, const krb5_data *indata, krb5_data *outdata)
{
    if (!indata) {
	return EINVAL;
    }

    outdata->length = indata->length;
    if (outdata->length) {
	if (!(outdata->data = malloc(outdata->length))) {
            krb5_xfree(outdata);
            return ENOMEM;
	}
        memcpy((char *)outdata->data, (char *)indata->data, outdata->length);
    } else
        outdata->data = 0;
    outdata->magic = KV5M_DATA;

    return 0;
}
Esempio n. 18
0
static krb5_error_code
get_keytab(krb5_context context, krb5_keytab *keytab)
{
    krb5_error_code kret;

    HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex);

    if (_gsskrb5_keytab != NULL) {
	char *name = NULL;

	kret = krb5_kt_get_full_name(context, _gsskrb5_keytab, &name);
	if (kret == 0) {
	    kret = krb5_kt_resolve(context, name, keytab);
	    krb5_xfree(name);
	}
    } else
	kret = krb5_kt_default(context, keytab);

    HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);

    return (kret);
}
Esempio n. 19
0
/*
 * krb5_principal_size()	- Determine the size required to externalize
 *				  the krb5_principal.
 */
static krb5_error_code
krb5_principal_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
{
    krb5_error_code	kret;
    krb5_principal	principal;
    char		*fname;

    /*
     * krb5_principal requires:
     *	krb5_int32			for KV5M_PRINCIPAL
     *	krb5_int32			for flattened name size
     *	strlen(name)			for name.
     *	krb5_int32			for KV5M_PRINCIPAL
     */
    kret = EINVAL;
    if ((principal = (krb5_principal) arg) &&
	!(kret = krb5_unparse_name(kcontext, principal, &fname))) {
	*sizep += (3*sizeof(krb5_int32)) + strlen(fname);
	krb5_xfree(fname);
    }
    return(kret);
}
Esempio n. 20
0
File: scache.c Progetto: hyc/heimdal
static krb5_error_code
bind_principal(krb5_context context,
	       sqlite3 *db,
	       sqlite3_stmt *stmt,
	       int col,
	       krb5_const_principal principal)
{
    krb5_error_code ret;
    char *str;

    ret = krb5_unparse_name(context, principal, &str);
    if (ret)
	return ret;

    ret = sqlite3_bind_text(stmt, col, str, -1, free_krb5);
    if (ret != SQLITE_OK) {
	krb5_xfree(str);
	krb5_set_error_message(context, ENOMEM,
			       N_("scache bind principal: %s", ""),
			       sqlite3_errmsg(db));
	return ENOMEM;
    }
    return 0;
}
Esempio n. 21
0
static const char* KRB5_CALLCONV
acc_get_name(krb5_context context,
	     krb5_ccache id)
{
    krb5_acc *a = ACACHE(id);
    int32_t error;

    if (a->cache_name == NULL) {
	krb5_error_code ret;
	krb5_principal principal;
	char *name;

	ret = _krb5_get_default_principal_local(context, &principal);
	if (ret)
	    return NULL;

	ret = krb5_unparse_name(context, principal, &name);
	krb5_free_principal(context, principal);
	if (ret)
	    return NULL;

	error = (*a->context->func->create_new_ccache)(a->context,
						       cc_credentials_v5,
						       name,
						       &a->ccache);
	krb5_xfree(name);
	if (error)
	    return NULL;

	error = get_cc_name(a);
	if (error)
	    return NULL;
    }

    return a->cache_name;
}
Esempio n. 22
0
static krb5_error_code
resolve_by_uuid_oid(krb5_context context, const krb5_cc_ops *ops, krb5_ccache id, krb5_uuid uuid)
{
    krb5_storage *request, *response;
    krb5_data response_data;
    krb5_error_code ret;
    char *name;
    ssize_t sret;
    
    ret = krb5_kcm_storage_request(context, KCM_OP_GET_CACHE_BY_UUID, &request);
    if (ret)
	return ret;
    
    sret = krb5_storage_write(request, uuid, sizeof(krb5_uuid));
    if (sret != sizeof(krb5_uuid)) {
	krb5_storage_free(request);
	krb5_clear_error_message(context);
	return ENOMEM;
    }
    
    ret = krb5_kcm_call(context, request, &response, &response_data);
    krb5_storage_free(request);
    if (ret)
	return ret;

    ret = krb5_ret_stringz(response, &name);
    krb5_storage_free(response);
    krb5_data_free(&response_data);
    if (ret)
	return ret;
    
    ret = kcm_alloc(context, name, &id);
    krb5_xfree(name);
    
    return ret;
}
Esempio n. 23
0
static krb5_error_code
krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
			const krb5_ap_req *req, krb5_const_principal server,
			krb5_keytab keytab, krb5_flags *ap_req_options,
			krb5_ticket **ticket, int check_valid_flag)
{
    krb5_error_code 	  retval = 0;
    krb5_timestamp 	  currenttime;
    krb5_principal_data princ_data;
    
    req->ticket->enc_part2 == NULL;
    if (server && krb5_is_referral_realm(&server->realm)) {
	char *realm;
	princ_data = *server;
	server = &princ_data;
	retval = krb5_get_default_realm(context, &realm);
	if (retval)
	    return retval;
	princ_data.realm.data = realm;
	princ_data.realm.length = strlen(realm);
    }
    if (server && !krb5_principal_compare(context, server, req->ticket->server)) {
	char *found_name = 0, *wanted_name = 0;
	if (krb5_unparse_name(context, server, &wanted_name) == 0
	    && krb5_unparse_name(context, req->ticket->server, &found_name) == 0)
	    krb5_set_error_message(context, KRB5KRB_AP_WRONG_PRINC,
				   "Wrong principal in request (found %s, wanted %s)",
				   found_name, wanted_name);
	krb5_free_unparsed_name(context, wanted_name);
	krb5_free_unparsed_name(context, found_name);
	retval =  KRB5KRB_AP_WRONG_PRINC;
	goto cleanup;
    }

    /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY)
       do we need special processing here ?	*/

    /* decrypt the ticket */
    if ((*auth_context)->keyblock) { /* User to User authentication */
    	if ((retval = krb5_decrypt_tkt_part(context, (*auth_context)->keyblock,
					    req->ticket)))
goto cleanup;
	krb5_free_keyblock(context, (*auth_context)->keyblock);
	(*auth_context)->keyblock = NULL;
    } else {
    	if ((retval = krb5_rd_req_decrypt_tkt_part(context, req, keytab)))
	    goto cleanup;
    }

    /* XXX this is an evil hack.  check_valid_flag is set iff the call
       is not from inside the kdc.  we can use this to determine which
       key usage to use */
    if ((retval = decrypt_authenticator(context, req, 
					&((*auth_context)->authentp),
					check_valid_flag)))
	goto cleanup;

    if (!krb5_principal_compare(context, (*auth_context)->authentp->client,
				req->ticket->enc_part2->client)) {
	retval = KRB5KRB_AP_ERR_BADMATCH;
	goto cleanup;
    }

    if ((*auth_context)->remote_addr && 
      !krb5_address_search(context, (*auth_context)->remote_addr, 
			   req->ticket->enc_part2->caddrs)) {
	retval = KRB5KRB_AP_ERR_BADADDR;
	goto cleanup;
    }

    /* okay, now check cross-realm policy */

#if defined(_SINGLE_HOP_ONLY)

    /* Single hop cross-realm tickets only */

    { 
	krb5_transited *trans = &(req->ticket->enc_part2->transited);

      	/* If the transited list is empty, then we have at most one hop */
      	if (trans->tr_contents.data && trans->tr_contents.data[0])
            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
    }

#elif defined(_NO_CROSS_REALM)

    /* No cross-realm tickets */

    { 
	char		* lrealm;
      	krb5_data      	* realm;
      	krb5_transited 	* trans;
  
	realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
	trans = &(req->ticket->enc_part2->transited);

	/*
      	 * If the transited list is empty, then we have at most one hop 
      	 * So we also have to check that the client's realm is the local one 
	 */
      	krb5_get_default_realm(context, &lrealm);
      	if ((trans->tr_contents.data && trans->tr_contents.data[0]) ||
          strlen(lrealm) != realm->length ||
          memcmp(lrealm, realm->data, strlen(lrealm))) {
            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
      	}
      	free(lrealm);
    }

#else

    /* Hierarchical Cross-Realm */
  
    {
      	krb5_data      * realm;
      	krb5_transited * trans;
  
	realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
	trans = &(req->ticket->enc_part2->transited);

	/*
      	 * If the transited list is not empty, then check that all realms 
      	 * transited are within the hierarchy between the client's realm  
      	 * and the local realm.                                        
  	 */
	if (trans->tr_contents.data && trans->tr_contents.data[0]) {
	    retval = krb5_check_transited_list(context, &(trans->tr_contents), 
					       realm,
					       krb5_princ_realm (context,
								 server));
      	}
    }

#endif

    if (retval)  goto cleanup;

    /* only check rcache if sender has provided one---some services
       may not be able to use replay caches (such as datagram servers) */

    if ((*auth_context)->rcache) {
	krb5_donot_replay  rep;
        krb5_tkt_authent   tktauthent;

	tktauthent.ticket = req->ticket;	
	tktauthent.authenticator = (*auth_context)->authentp;
	if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) {
	    retval = krb5_rc_store(context, (*auth_context)->rcache, &rep);
	    krb5_xfree(rep.server);
	    krb5_xfree(rep.client);
	}

	if (retval)
	    goto cleanup;
    }

    retval = krb5_validate_times(context, &req->ticket->enc_part2->times);
    if (retval != 0)
	    goto cleanup;

    if ((retval = krb5_timeofday(context, &currenttime)))
	goto cleanup;

    if (!in_clock_skew((*auth_context)->authentp->ctime)) {
	retval = KRB5KRB_AP_ERR_SKEW;
	goto cleanup;
    }

    if (check_valid_flag) {
      if (req->ticket->enc_part2->flags & TKT_FLG_INVALID) {
	retval = KRB5KRB_AP_ERR_TKT_INVALID;
	goto cleanup;
      }
    }

    /* check if the various etypes are permitted */

    if ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) {
	/* no etype check needed */;
    } else if ((*auth_context)->permitted_etypes == NULL) {
	int etype;
	/* check against the default set */
	if ((!krb5_is_permitted_enctype(context,
					etype = req->ticket->enc_part.enctype)) ||
	    (!krb5_is_permitted_enctype(context,
					etype = req->ticket->enc_part2->session->enctype)) ||
	    (((*auth_context)->authentp->subkey) &&
	     !krb5_is_permitted_enctype(context,
					etype = (*auth_context)->authentp->subkey->enctype))) {
	    char enctype_name[30];
	    retval = KRB5_NOPERM_ETYPE;
	    if (krb5_enctype_to_string(etype, enctype_name, sizeof(enctype_name)) == 0)
		krb5_set_error_message(context, retval,
				       "Encryption type %s not permitted",
				       enctype_name);
	    goto cleanup;
	}
    } else {
	/* check against the set in the auth_context */
	int i;

	for (i=0; (*auth_context)->permitted_etypes[i]; i++)
	    if ((*auth_context)->permitted_etypes[i] ==
		req->ticket->enc_part.enctype)
		break;
	if (!(*auth_context)->permitted_etypes[i]) {
	    char enctype_name[30];
	    retval = KRB5_NOPERM_ETYPE;
	    if (krb5_enctype_to_string(req->ticket->enc_part.enctype,
				       enctype_name, sizeof(enctype_name)) == 0)
		krb5_set_error_message(context, retval,
				       "Encryption type %s not permitted",
				       enctype_name);
	    goto cleanup;
	}
	
	for (i=0; (*auth_context)->permitted_etypes[i]; i++)
	    if ((*auth_context)->permitted_etypes[i] ==
		req->ticket->enc_part2->session->enctype)
		break;
	if (!(*auth_context)->permitted_etypes[i]) {
	    char enctype_name[30];
	    retval = KRB5_NOPERM_ETYPE;
	    if (krb5_enctype_to_string(req->ticket->enc_part2->session->enctype,
				       enctype_name, sizeof(enctype_name)) == 0)
		krb5_set_error_message(context, retval,
				       "Encryption type %s not permitted",
				       enctype_name);
	    goto cleanup;
	}
	
	if ((*auth_context)->authentp->subkey) {
	    for (i=0; (*auth_context)->permitted_etypes[i]; i++)
		if ((*auth_context)->permitted_etypes[i] ==
		    (*auth_context)->authentp->subkey->enctype)
		    break;
	    if (!(*auth_context)->permitted_etypes[i]) {
		char enctype_name[30];
		retval = KRB5_NOPERM_ETYPE;
		if (krb5_enctype_to_string((*auth_context)->authentp->subkey->enctype,
					   enctype_name,
					   sizeof(enctype_name)) == 0)
		    krb5_set_error_message(context, retval,
					   "Encryption type %s not permitted",
					   enctype_name);
		goto cleanup;
	    }
	}
    }

    (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number;
    if ((*auth_context)->authentp->subkey) {
	if ((retval = krb5_copy_keyblock(context,
					 (*auth_context)->authentp->subkey,
					 &((*auth_context)->recv_subkey))))
	    goto cleanup;
	retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey,
				    &((*auth_context)->send_subkey));
	if (retval) {
	    krb5_free_keyblock(context, (*auth_context)->recv_subkey);
	    (*auth_context)->recv_subkey = NULL;
	    goto cleanup;
	}
    } else {
	(*auth_context)->recv_subkey = 0;
	(*auth_context)->send_subkey = 0;
    }

    if ((retval = krb5_copy_keyblock(context, req->ticket->enc_part2->session,
				     &((*auth_context)->keyblock))))
	goto cleanup;

    /*
     * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used 
     * then the default sequence number is the one's complement of the
     * sequence number sent ot us.
     */
    if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) && 
      (*auth_context)->remote_seq_number) {
	(*auth_context)->local_seq_number ^= 
	  (*auth_context)->remote_seq_number;
    }

    if (ticket)
   	if ((retval = krb5_copy_ticket(context, req->ticket, ticket)))
	    goto cleanup;
    if (ap_req_options)
    	*ap_req_options = req->ap_options;
    retval = 0;
    
cleanup:
    if (server == &princ_data)
	krb5_free_default_realm(context, princ_data.realm.data);
    if (retval) {
	/* only free if we're erroring out...otherwise some
	   applications will need the output. */
	if (req->ticket->enc_part2)
	    krb5_free_enc_tkt_part(context, req->ticket->enc_part2);
	req->ticket->enc_part2 = NULL;
    }
    return retval;
}
Esempio n. 24
0
/*
 * This function will create a krbcontainer and realm on the LDAP Server, with
 * the specified attributes.
 */
krb5_error_code
krb5_ldap_create(krb5_context context, char *conf_section, char **db_args)
{
    krb5_error_code status = 0;
    char  **t_ptr = db_args;
    krb5_ldap_realm_params *rparams = NULL;
    kdb5_dal_handle *dal_handle = NULL;
    krb5_ldap_context *ldap_context=NULL;
    krb5_boolean realm_obj_created = FALSE;
    krb5_boolean krbcontainer_obj_created = FALSE;
    krb5_ldap_krbcontainer_params kparams = {0};
    int srv_cnt = 0;
    int mask = 0;

    /* Clear the global error string */
    krb5_clear_error_message(context);

    ldap_context = malloc(sizeof(krb5_ldap_context));
    if (ldap_context == NULL) {
        status = ENOMEM;
        goto cleanup;
    }
    memset(ldap_context, 0, sizeof(*ldap_context));

    ldap_context->kcontext = context;

    /* populate ldap_context with ldap specific options */
    while (t_ptr && *t_ptr) {
        char *opt = NULL, *val = NULL;

        if ((status = krb5_ldap_get_db_opt(*t_ptr, &opt, &val)) != 0) {
            goto cleanup;
        }
        if (opt && !strcmp(opt, "binddn")) {
            if (ldap_context->bind_dn) {
                free (opt);
                free (val);
                status = EINVAL;
                krb5_set_error_message (context, status, "'binddn' missing");
                goto cleanup;
            }
            if (val == NULL) {
                status = EINVAL;
                krb5_set_error_message (context, status, "'binddn' value missing");
                free(opt);
                goto cleanup;
            }
            ldap_context->bind_dn = strdup(val);
            if (ldap_context->bind_dn == NULL) {
                free (opt);
                free (val);
                status = ENOMEM;
                goto cleanup;
            }
        } else if (opt && !strcmp(opt, "nconns")) {
            if (ldap_context->max_server_conns) {
                free (opt);
                free (val);
                status = EINVAL;
                krb5_set_error_message (context, status, "'nconns' missing");
                goto cleanup;
            }
            if (val == NULL) {
                status = EINVAL;
                krb5_set_error_message (context, status, "'nconns' value missing");
                free(opt);
                goto cleanup;
            }
            ldap_context->max_server_conns = atoi(val) ? atoi(val) : DEFAULT_CONNS_PER_SERVER;
        } else if (opt && !strcmp(opt, "bindpwd")) {
            if (ldap_context->bind_pwd) {
                free (opt);
                free (val);
                status = EINVAL;
                krb5_set_error_message (context, status, "'bindpwd' missing");
                goto cleanup;
            }
            if (val == NULL) {
                status = EINVAL;
                krb5_set_error_message (context, status, "'bindpwd' value missing");
                free(opt);
                goto cleanup;
            }
            ldap_context->bind_pwd = strdup(val);
            if (ldap_context->bind_pwd == NULL) {
                free (opt);
                free (val);
                status = ENOMEM;
                goto cleanup;
            }
        } else if (opt && !strcmp(opt, "host")) {
            if (val == NULL) {
                status = EINVAL;
                krb5_set_error_message (context, status, "'host' value missing");
                free(opt);
                goto cleanup;
            }
            if (ldap_context->server_info_list == NULL)
                ldap_context->server_info_list =
                    (krb5_ldap_server_info **) calloc(SERV_COUNT+1, sizeof(krb5_ldap_server_info *));

            if (ldap_context->server_info_list == NULL) {
                free (opt);
                free (val);
                status = ENOMEM;
                goto cleanup;
            }

            ldap_context->server_info_list[srv_cnt] =
                (krb5_ldap_server_info *) calloc(1, sizeof(krb5_ldap_server_info));
            if (ldap_context->server_info_list[srv_cnt] == NULL) {
                free (opt);
                free (val);
                status = ENOMEM;
                goto cleanup;
            }

            ldap_context->server_info_list[srv_cnt]->server_status = NOTSET;

            ldap_context->server_info_list[srv_cnt]->server_name = strdup(val);
            if (ldap_context->server_info_list[srv_cnt]->server_name == NULL) {
                free (opt);
                free (val);
                status = ENOMEM;
                goto cleanup;
            }

            srv_cnt++;
        } else {
            /* ignore hash argument. Might have been passed from create */
            status = EINVAL;
            if (opt && !strcmp(opt, "temporary")) {
                /*
                 * temporary is passed in when kdb5_util load without -update is done.
                 * This is unsupported by the LDAP plugin.
                 */
                krb5_set_error_message(context, status,
                                       _("creation of LDAP entries aborted, "
                                         "plugin requires -update argument"));
            } else {
                krb5_set_error_message(context, status,
                                       _("unknown option \'%s\'"),
                                       opt?opt:val);
            }
            free(opt);
            free(val);
            goto cleanup;
        }

        free(opt);
        free(val);
        t_ptr++;
    }

    dal_handle = context->dal_handle;
    dal_handle->db_context = (kdb5_dal_handle *) ldap_context;

    status = krb5_ldap_read_server_params(context, conf_section, KRB5_KDB_SRV_TYPE_ADMIN);
    if (status) {
        dal_handle->db_context = NULL;
        prepend_err_str (context, "Error reading LDAP server params: ", status, status);
        goto cleanup;
    }
    status = krb5_ldap_db_init(context, ldap_context);
    if (status) {
        goto cleanup;
    }

    /* read the kerberos container */
    if ((status = krb5_ldap_read_krbcontainer_params(context,
                                                     &(ldap_context->krbcontainer))) == KRB5_KDB_NOENTRY) {

        /* Read the kerberos container location from configuration file */
        if (ldap_context->conf_section) {
            if ((status = profile_get_string(context->profile,
                                             KDB_MODULE_SECTION, ldap_context->conf_section,
                                             KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN, NULL,
                                             &kparams.DN)) != 0) {
                goto cleanup;
            }
        }
        if (kparams.DN == NULL) {
            if ((status = profile_get_string(context->profile,
                                             KDB_MODULE_DEF_SECTION,
                                             KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN, NULL,
                                             NULL, &kparams.DN)) != 0) {
                goto cleanup;
            }
        }

        /* create the kerberos container */
        status = krb5_ldap_create_krbcontainer(context,
                                               ((kparams.DN != NULL) ? &kparams : NULL));
        if (status)
            goto cleanup;

        krbcontainer_obj_created = TRUE;

        status = krb5_ldap_read_krbcontainer_params(context,
                                                    &(ldap_context->krbcontainer));
        if (status)
            goto cleanup;

    } else if (status) {
        goto cleanup;
    }

    rparams = (krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params));
    if (rparams == NULL) {
        status = ENOMEM;
        goto cleanup;
    }
    memset(rparams, 0, sizeof(*rparams));
    rparams->realm_name = strdup(context->default_realm);
    if (rparams->realm_name == NULL) {
        status = ENOMEM;
        goto cleanup;
    }

    if ((status = krb5_ldap_create_realm(context, rparams, mask)))
        goto cleanup;

    /* We just created the Realm container. Here starts our transaction tracking */
    realm_obj_created = TRUE;

    /* verify realm object */
    if ((status = krb5_ldap_read_realm_params(context,
                                              rparams->realm_name,
                                              &(ldap_context->lrparams),
                                              &mask)))
        goto cleanup;

cleanup:

    /* If the krbcontainer/realm creation is not complete, do the roll-back here */
    if ((krbcontainer_obj_created) && (!realm_obj_created)) {
        int rc;
        rc = krb5_ldap_delete_krbcontainer(context,
                                           ((kparams.DN != NULL) ? &kparams : NULL));
        krb5_set_error_message(context, rc,
                               _("could not complete roll-back, error "
                                 "deleting Kerberos Container"));
    }

    /* should call krb5_ldap_free_krbcontainer_params() but can't */
    if (kparams.DN != NULL)
        krb5_xfree(kparams.DN);

    if (rparams)
        krb5_ldap_free_realm_params(rparams);

    return(status);
}
Esempio n. 25
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;
}
Esempio n. 26
0
int do_krb5_comm(krb5_context context, krb5_keytab keytab, krb5_principal server, char *cmddir) {
	struct sockaddr_in c_saddr, s_saddr;
	socklen_t namelen;
	int sock = 0;
	int len;
	char buff[BUFFSIZE];
	char *cname = NULL;
	krb5_error_code retval;
	krb5_data kdata, message;
	krb5_auth_context auth_context = NULL;
	krb5_ticket *ticket;
	krb5_address ckaddr, skaddr;
	krb5_rcache rcache;
	krb5_data rcache_name;
	long srand, rrand;
	int fd[2];
	char rcname_piece[RC_PIECE_MAXLEN];

	namelen = sizeof(c_saddr);
	if (getpeername(sock, (struct sockaddr *)&c_saddr, &namelen) < 0) {
		syslog(LOG_ERR, "getpeername: %m");
		return 1;
	}

	namelen = sizeof(s_saddr);
	if (getsockname(sock, (struct sockaddr *)&s_saddr, &namelen) < 0) {
		syslog(LOG_ERR, "getsockname: %m");
		return 1;
	}

	/* INIT MSG = random number */
	srand = random();

	/* Send it */
	if (send(sock, &srand, sizeof(srand), 0) < 0) {
		syslog(LOG_ERR, "%m while sending init message");
		return 1;
	}
	if (recv(sock, &rrand, sizeof(rrand), 0) < 0) {
		syslog(LOG_ERR, "%m while receiving init reply");
		return 1;
	}

	/* Reply should contain the same message (number) */
	if (srand != rrand) {
		syslog(LOG_ERR, "Bad init reply");
		return 1;
	}

	/* Do authentication */
	if (retval = krb5_recvauth(context, &auth_context, (krb5_pointer)&sock, AFSADM_VERSION, server, 0, keytab, &ticket)) {
		syslog(LOG_ERR, "recvauth failed: %s", error_message(retval));
		exit(1);
	}

	/* Get client name */
	if (retval = krb5_unparse_name(context, ticket->enc_part2->client, &cname)) {
		syslog(LOG_ERR, "unparse failed: %s", error_message(retval));
		return 1;
	}

	if (ticket)
		krb5_free_ticket(context, ticket);

	if (debug)
		syslog(LOG_DEBUG, "Principal %s", cname);

	/*******************************************************************/

	ckaddr.addrtype = ADDRTYPE_IPPORT;
	ckaddr.length   = sizeof(c_saddr.sin_port);
	ckaddr.contents = (krb5_octet *)&c_saddr.sin_port;

	skaddr.addrtype = ADDRTYPE_IPPORT;
	skaddr.length   = sizeof(s_saddr.sin_port);
	skaddr.contents = (krb5_octet *)&s_saddr.sin_port;
	if ((retval = krb5_auth_con_setports(context, auth_context, &skaddr, &ckaddr))) {
		syslog(LOG_ERR, "%s while setting ports", error_message(retval));
		return 1;
	}

	/* Set foreign_addr for rd_priv() */
	ckaddr.addrtype = ADDRTYPE_INET;
	ckaddr.length   = sizeof(c_saddr.sin_addr);
	ckaddr.contents = (krb5_octet *)&c_saddr.sin_addr;

	/* Set local_addr  */
	skaddr.addrtype = ADDRTYPE_INET;
	skaddr.length   = sizeof(s_saddr.sin_addr);
	skaddr.contents = (krb5_octet *)&s_saddr.sin_addr;

	if ((retval = krb5_auth_con_setaddrs(context, auth_context, &skaddr, &ckaddr))) {
		syslog(LOG_ERR, "%s while setting addrs", error_message(retval));
		return 1;
	}

	/* Receive a request */
	if ((len = recv(sock, (char *)buff, sizeof(buff), 0)) < 0) {
		syslog(LOG_ERR, "%m while receiving datagram");
		return 1;
	}

	kdata.length = len;
	kdata.data = buff;

	if (debug)
		syslog(LOG_DEBUG, "Received %d bytes", len);

	/* Decrypt it */
	if ((retval = krb5_rd_priv(context, auth_context, &kdata, &message, NULL))) {
		syslog(LOG_ERR, "%s while verifying PRIV message", error_message(retval));
		return 1;
	}

	if (message.length > 0) {
#ifdef __osf__
		sprintf(rcname_piece, "afsadmd_%d",  getpid());
#else
		snprintf(rcname_piece, RC_PIECE_MAXLEN, "afsadmd_%d", getpid());
#endif
		rcache_name.data = rcname_piece;
		rcache_name.length = strlen(rcache_name.data);

		if ((retval = krb5_get_server_rcache(context, &rcache_name, &rcache))) {
			syslog(LOG_ERR, "%s while getting server rcache", error_message(retval));
			return 1;
		}

		/* set auth_context rcache */
		if (retval = krb5_auth_con_setrcache(context, auth_context, rcache)) {
			syslog(LOG_ERR, "%s while setting rcache", error_message(retval));
			return 1;
		}

		/*********************************************************************
		 * Call the desired command, read stdout/stderr, send it
		 *********************************************************************/

		/* create fork */
		if (pipe(fd) == -1)
			printf("Failed create fork with pipe().\n");

		if (fork() == 0) {
			close(fd[0]);
			close(1);
			close(2);
			dup2(fd[1], 1);
			dup2(fd[1], 2);

			/* Call required command */
			do_command(context, keytab, server, cname, message.data, cmddir );
			krb5_xfree(message.data);
			exit(0);
		} else {
			/* Read stdout/stderr from pipe, store it to the buffer, encrypt it a send to the client */
			krb5_data message, kdata;
			char buff[PIPEBUFF];
			int n = 0;
			int len = 0;
			int sent = 0;
			int counter = 0;
			int end = 0;
			short netlen;
			time_t starttime, oldtime, newtime;
			FILE *pipedes;

			close(fd[1]);
			pipedes = fdopen(fd[0], "r");

			starttime = oldtime = time(NULL);

			for (n = 0; end == 0; ) {
				/* Read line from pipe */
				if (fgets(buff + n, PIPEBUFF - n, pipedes) == NULL)
					end++;
				else
					n = strlen(buff);

				/* Get time */
				newtime = time(NULL);

				/* Send buffer when
				 *    a) buffer is full
				 *    b) buffer contains data and
				 *      1) end-of-file encountered (end flag)
				 *      2) buffer sent before 1s
				 */
				if ((n == PIPEBUFF) || (((newtime > oldtime) || end ) && (n != 0))) {
					/* Prepare data for sending */
					message.data = buff;
					message.length = n;
					kdata.data = NULL;

					/* Make the encrypted message */
					if ((retval = krb5_mk_priv(context, auth_context, &message, &kdata, NULL))) {
						syslog(LOG_ERR, "%s while making KRB_PRIV message", error_message(retval));
						return 1;
					}

					/* Convert byte order */
					netlen = htons((short)kdata.length);

					/* Send len of encrypted data */
					if ((len = send(sock, (char *)&netlen, sizeof(netlen), 0)) != sizeof(netlen)) {
						krb5_xfree(kdata.data);
						syslog(LOG_ERR, "%m while sending len of PRIV message");
						return 1;
					}

					/* Send it */
					if ((len = send(sock, (char *)kdata.data, kdata.length, 0)) != kdata.length) {
						syslog(LOG_ERR, "%m while sending PRIV message");
						krb5_xfree(kdata.data);
						return 1;
					}

					/* Statistics */
					sent += len;
					counter++;

					/* Timestanmp */
					oldtime = newtime;
					n = 0;

					krb5_xfree(kdata.data);
				}
			}

			newtime = time(NULL);

			if (debug)
				syslog(LOG_DEBUG, "Sent %d bytes in %ds [%d fragment(s)]", sent, (int)(newtime - starttime),  counter);
		}
	}

	//FIXME: There is no way to close or destroy rcache declared in krb5 headers
	//krb5_rc_destroy(context, rcache);

	/* set auth_context rcache */
	if (retval = krb5_auth_con_setrcache(context, auth_context, rcache)) {
		syslog(LOG_ERR, "%s while setting rcache to NULL", error_message(retval));
		return 1;
	}

	free(cname);
	krb5_auth_con_free(context, auth_context);
	return 0;
}
Esempio n. 27
0
krb5_error_code KRB5_CALLCONV
krb5_425_conv_principal(krb5_context context, const char *name,
			const char *instance, const char *realm,
			krb5_principal *princ)
{
     const struct krb_convert *p;
     char buf[256];		/* V4 instances are limited to 40 characters */
     krb5_error_code retval;
     char *domain, *cp;
     char **full_name = 0;
     const char *names[5], *names2[2];
     void*	iterator = NULL;
     char** v4realms = NULL;
     char* realm_name = NULL;
     char* dummy_value = NULL;
     
     /* First, convert the realm, since the v4 realm is not necessarily the same as the v5 realm
        To do that, iterate over all the realms in the config file, looking for a matching 
        v4_realm line */
     names2 [0] = "realms";
     names2 [1] = NULL;
     retval = profile_iterator_create (context -> profile, names2, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, &iterator);
     while (retval == 0) {
     	retval = profile_iterator (&iterator, &realm_name, &dummy_value);
     	if ((retval == 0) && (realm_name != NULL)) {
     		names [0] = "realms";
     		names [1] = realm_name;
     		names [2] = "v4_realm";
     		names [3] = NULL;

     		retval = profile_get_values (context -> profile, names, &v4realms);
     		if ((retval == 0) && (v4realms != NULL) && (v4realms [0] != NULL) && (strcmp (v4realms [0], realm) == 0)) {
     			realm = realm_name;
     			break;
     		} else if (retval == PROF_NO_RELATION) {
     			/* If it's not found, just keep going */
     			retval = 0;
     		}
     	} else if ((retval == 0) && (realm_name == NULL)) {
     		break;
     	}
	if (v4realms != NULL) {
	        profile_free_list(v4realms);
		v4realms = NULL;
	}
     	if (realm_name != NULL) {
     		profile_release_string (realm_name);
     		realm_name = NULL;
     	}
     	if (dummy_value != NULL) {
     		profile_release_string (dummy_value);
     		dummy_value = NULL;
     	}
     }
     
     if (instance) {
	  if (instance[0] == '\0') {
	       instance = 0;
	       goto not_service;
	  }
	  p = sconv_list;
	  while (1) {
	       if (!p->v4_str)
		    goto not_service;
	       if (!strcmp(p->v4_str, name))
		    break;
	       p++;
	  }
	  name = p->v5_str;
	  if ((p->flags & DO_REALM_CONVERSION) && !strchr(instance, '.')) {
	      names[0] = "realms";
	      names[1] = realm;
	      names[2] = "v4_instance_convert";
	      names[3] = instance;
	      names[4] = 0;
	      retval = profile_get_values(context->profile, names, &full_name);
	      if (retval == 0 && full_name && full_name[0]) {
		  instance = full_name[0];
	      } else {
		  strncpy(buf, instance, sizeof(buf));
		  buf[sizeof(buf) - 1] = '\0';
		  retval = krb5_get_realm_domain(context, realm, &domain);
		  if (retval)
		      return retval;
		  if (domain) {
		      for (cp = domain; *cp; cp++)
			  if (isupper((unsigned char) (*cp)))
			      *cp = tolower((unsigned char) *cp);
		      strncat(buf, ".", sizeof(buf) - 1 - strlen(buf));
		      strncat(buf, domain, sizeof(buf) - 1 - strlen(buf));
		      krb5_xfree(domain);
		  }
		  instance = buf;
	      }
	  }
     }
     
not_service:
     retval = krb5_build_principal(context, princ, strlen(realm), realm, name,
				   instance, NULL);
     if (iterator) profile_iterator_free (&iterator);
     if (full_name) profile_free_list(full_name);
     if (v4realms) profile_free_list(v4realms);
     if (realm_name) profile_release_string (realm_name);
     if (dummy_value) profile_release_string (dummy_value);
     return retval;
}
Esempio n. 28
0
File: kdb5.c Progetto: aosm/Kerberos
krb5_error_code
krb5_db_fetch_mkey(krb5_context context,
		   krb5_principal mname,
		   krb5_enctype etype,
		   krb5_boolean fromkeyboard,
		   krb5_boolean twice,
		   char *db_args, krb5_data * salt, krb5_keyblock * key)
{
    krb5_error_code retval;
    char    password[BUFSIZ];
    krb5_data pwd;
    unsigned int size = sizeof(password);
    int     kvno;
    krb5_keyblock tmp_key;

    memset(&tmp_key, 0, sizeof(tmp_key));

    if (fromkeyboard) {
	krb5_data scratch;

	if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1,
					 twice ? krb5_mkey_pwd_prompt2 : 0,
					 password, &size))) {
	    goto clean_n_exit;
	}

	pwd.data = password;
	pwd.length = size;
	if (!salt) {
	    retval = krb5_principal2salt(context, mname, &scratch);
	    if (retval)
		goto clean_n_exit;
	}
	retval =
	    krb5_c_string_to_key(context, etype, &pwd, salt ? salt : &scratch,
				 key);

	if (!salt)
	    krb5_xfree(scratch.data);
	memset(password, 0, sizeof(password));	/* erase it */

    } else {
	kdb5_dal_handle *dal_handle;

	if (context->db_context == NULL) {
	    retval = kdb_setup_lib_handle(context);
	    if (retval) {
		goto clean_n_exit;
	    }
	}

	dal_handle = (kdb5_dal_handle *) context->db_context;
	retval = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
	if (retval) {
	    goto clean_n_exit;
	}

	tmp_key.enctype = key->enctype;
	retval = dal_handle->lib_handle->vftabl.fetch_master_key(context,
								 mname,
								 &tmp_key,
								 &kvno,
								 db_args);
	get_errmsg(context, retval);
	kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);

	if (retval) {
	    goto clean_n_exit;
	}

	key->contents = malloc(tmp_key.length);
	if (key->contents == NULL) {
	    retval = ENOMEM;
	    goto clean_n_exit;
	}

	key->magic = tmp_key.magic;
	key->enctype = tmp_key.enctype;
	key->length = tmp_key.length;
	memcpy(key->contents, tmp_key.contents, tmp_key.length);
    }

  clean_n_exit:
    if (tmp_key.contents) {
	memset(tmp_key.contents, 0, tmp_key.length);
	krb5_db_free(context, tmp_key.contents);
    }
    return retval;
}
Esempio n. 29
0
krb5_error_code KRB5_CALLCONV
krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, char *appl_version, krb5_principal client, krb5_principal server, krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, krb5_error **error, krb5_ap_rep_enc_part **rep_result, krb5_creds **out_creds)
{
	krb5_octet		result;
	krb5_creds 		creds;
	krb5_creds		 * credsp = NULL;
	krb5_creds		 * credspout = NULL;
	krb5_error_code		retval = 0;
	krb5_data		inbuf, outbuf;
	int			len;
	krb5_ccache		use_ccache = 0;

	if (error)
	    *error = 0;

	/*
	 * First, send over the length of the sendauth version string;
	 * then, we send over the sendauth version.  Next, we send
	 * over the length of the application version strings followed
	 * by the string itself.
	 */
	outbuf.length = strlen(sendauth_version) + 1;
	outbuf.data = (char *) sendauth_version;
	if ((retval = krb5_write_message(context, fd, &outbuf)))
		return(retval);
	outbuf.length = strlen(appl_version) + 1;
	outbuf.data = appl_version;
	if ((retval = krb5_write_message(context, fd, &outbuf)))
		return(retval);
	/*
	 * Now, read back a byte: 0 means no error, 1 means bad sendauth
	 * version, 2 means bad application version
	 */
	len = krb5_net_read(context, *((int *) fd), (char *)&result, 1);
	if (len != 1)
		return((len < 0) ? errno : ECONNABORTED);
	if (result == 1)
		return(KRB5_SENDAUTH_BADAUTHVERS);
	else if (result == 2)
		return(KRB5_SENDAUTH_BADAPPLVERS);
	else if (result != 0)
		return(KRB5_SENDAUTH_BADRESPONSE);
	/*
	 * We're finished with the initial negotiations; let's get and
	 * send over the authentication header.  (The AP_REQ message)
	 */

	/*
	 * If no credentials were provided, try getting it from the
	 * credentials cache.
	 */
	memset((char *)&creds, 0, sizeof(creds));

	/*
	 * See if we need to access the credentials cache
	 */
	if (!in_creds || !in_creds->ticket.length) {
		if (ccache)
			use_ccache = ccache;
		/* Solaris Kerberos */
		else if ((retval = krb5int_cc_default(context, &use_ccache)) != 0)
			goto error_return;
	}
	if (!in_creds) {
		if ((retval = krb5_copy_principal(context, server,
						  &creds.server)))
			goto error_return;
		if (client)
			retval = krb5_copy_principal(context, client,
						     &creds.client);
		else
			retval = krb5_cc_get_principal(context, use_ccache,
						       &creds.client);
		if (retval) {
			krb5_free_principal(context, creds.server);
			goto error_return;
		}
		/* creds.times.endtime = 0; -- memset 0 takes care of this
					zero means "as long as possible" */
		/* creds.keyblock.enctype = 0; -- as well as this.
					zero means no session enctype
					preference */
		in_creds = &creds;
	}
	if (!in_creds->ticket.length) {
		/* Solaris Kerberos */
	    if ((retval = krb5_get_credentials(context, 0,
					       use_ccache, in_creds, &credsp)) != 0)
		    goto error_return;
	    credspout = credsp;
	} else {
	    credsp = in_creds;
	}

	if (ap_req_options & AP_OPTS_USE_SUBKEY) {
	    /* Provide some more fodder for random number code.
	       This isn't strong cryptographically; the point here is
	       not to guarantee randomness, but to make it less likely
	       that multiple sessions could pick the same subkey.  */
	    char rnd_data[1024];
	    GETPEERNAME_ARG3_TYPE len2;
	    krb5_data d;
	    d.length = sizeof (rnd_data);
	    d.data = rnd_data;
	    len2 = sizeof (rnd_data);
	    if (getpeername (*(int*)fd, (GETPEERNAME_ARG2_TYPE *) rnd_data,
			     &len2) == 0) {
		d.length = len2;
		/* Solaris Kerberos */
		(void) krb5_c_random_seed (context, &d);
	    }
	    len2 = sizeof (rnd_data);
	    if (getsockname (*(int*)fd, (GETSOCKNAME_ARG2_TYPE *) rnd_data,
			     &len2) == 0) {
		d.length = len2;
		/* Solaris Kerberos */
		(void) krb5_c_random_seed (context, &d);
	    }
	}

	/* Solaris Kerberos */
	if ((retval = krb5_mk_req_extended(context, auth_context,
					   ap_req_options, in_data, credsp,
					   &outbuf)) != 0)
	    goto error_return;

	/*
	 * First write the length of the AP_REQ message, then write
	 * the message itself.
	 */
	retval = krb5_write_message(context, fd, &outbuf);
	free(outbuf.data);
	if (retval)
	    goto error_return;

	/*
	 * Now, read back a message.  If it was a null message (the
	 * length was zero) then there was no error.  If not, we the
	 * authentication was rejected, and we need to return the
	 * error structure.
	 */
	/* Solaris Kerberos */
	if ((retval = krb5_read_message(context, fd, &inbuf)) != 0)
	    goto error_return;

	if (inbuf.length) {
		if (error) {
		    /* Solaris Kerberos */
		    if ((retval = krb5_rd_error(context, &inbuf, error)) != 0) {
			krb5_xfree(inbuf.data);
			goto error_return;
		    }
		}
		retval = KRB5_SENDAUTH_REJECTED;
		krb5_xfree(inbuf.data);
		goto error_return;
	}

	/*
	 * If we asked for mutual authentication, we should now get a
	 * length field, followed by a AP_REP message
	 */
	if ((ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) {
	    krb5_ap_rep_enc_part	*repl = 0;
	    /* Solaris Kerberos */
	    if ((retval = krb5_read_message(context, fd, &inbuf)) != 0)
		goto error_return;

	    /* Solaris Kerberos */
	    if ((retval = krb5_rd_rep(context, *auth_context, &inbuf,
				      &repl)) != 0) {
		if (repl)
		    krb5_free_ap_rep_enc_part(context, repl);
	        krb5_xfree(inbuf.data);
		goto error_return;
	    }

	    krb5_xfree(inbuf.data);
	    /*
	     * If the user wants to look at the AP_REP message,
	     * copy it for them.
	     */
	    if (rep_result)
		*rep_result = repl;
	    else
		krb5_free_ap_rep_enc_part(context, repl);
	}
	retval = 0;		/* Normal return */
	if (out_creds) {
	    *out_creds = credsp;
	    credspout = NULL;
	}

error_return:
    krb5_free_cred_contents(context, &creds);
    if (credspout != NULL)
	krb5_free_creds(context, credspout);
    /* Solaris Kerberos */
    if (!ccache && use_ccache)
	(void) krb5_cc_close(context, use_ccache);
    return(retval);
}
Esempio n. 30
0
static int
list_caches(krb5_context context)
{
    krb5_cc_cache_cursor cursor;
    const char *cdef_name;
    char *def_name;
    krb5_error_code ret;
    krb5_ccache id;
    rtbl_t ct;

    cdef_name = krb5_cc_default_name(context);
    if (cdef_name == NULL)
	krb5_errx(context, 1, "krb5_cc_default_name");
    def_name = strdup(cdef_name);

    ret = krb5_cc_cache_get_first (context, NULL, &cursor);
    if (ret == KRB5_CC_NOSUPP)
	return 0;
    else if (ret)
	krb5_err (context, 1, ret, "krb5_cc_cache_get_first");

    ct = rtbl_create();
    rtbl_add_column(ct, COL_NAME, 0);
    rtbl_add_column(ct, COL_CACHENAME, 0);
    rtbl_add_column(ct, COL_EXPIRES, 0);
    rtbl_add_column(ct, COL_DEFCACHE, 0);
    rtbl_set_prefix(ct, "   ");
    rtbl_set_column_prefix(ct, COL_NAME, "");

    while (krb5_cc_cache_next (context, cursor, &id) == 0) {
	krb5_principal principal = NULL;
	int expired = 0;
	char *name;
	time_t t;

	ret = krb5_cc_get_principal(context, id, &principal);
	if (ret)
	    continue;

	expired = check_for_tgt (context, id, principal, &t);

	ret = krb5_cc_get_friendly_name(context, id, &name);
	if (ret == 0) {
	    const char *str;
	    char *fname;
	    rtbl_add_column_entry(ct, COL_NAME, name);
	    rtbl_add_column_entry(ct, COL_CACHENAME,
				  krb5_cc_get_name(context, id));
	    if (expired)
		str = N_(">>> Expired <<<", "");
	    else
		str = printable_time(t);
	    rtbl_add_column_entry(ct, COL_EXPIRES, str);
	    free(name);

	    ret = krb5_cc_get_full_name(context, id, &fname);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_cc_get_full_name");

	    if (strcmp(fname, def_name) == 0)
		rtbl_add_column_entry(ct, COL_DEFCACHE, "*");
	    else
		rtbl_add_column_entry(ct, COL_DEFCACHE, "");

	    krb5_xfree(fname);
	}
	krb5_cc_close(context, id);

	krb5_free_principal(context, principal);
    }

    krb5_cc_cache_end_seq_get(context, cursor);

    free(def_name);
    rtbl_format(ct, stdout);
    rtbl_destroy(ct);

    return 0;
}