Beispiel #1
0
OM_uint32 GSSAPI_CALLCONV
_gsskrb5_delete_sec_context(OM_uint32 * minor_status,
			    gss_ctx_id_t * context_handle,
			    gss_buffer_t output_token)
{
    krb5_context context;
    gsskrb5_ctx ctx;

    GSSAPI_KRB5_INIT (&context);

    *minor_status = 0;

    if (output_token) {
	output_token->length = 0;
	output_token->value  = NULL;
    }

    if (*context_handle == GSS_C_NO_CONTEXT)
	return GSS_S_COMPLETE;

    ctx = (gsskrb5_ctx) *context_handle;
    *context_handle = GSS_C_NO_CONTEXT;

    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);

    krb5_auth_con_free (context, ctx->auth_context);
    krb5_auth_con_free (context, ctx->deleg_auth_context);
    if (ctx->kcred)
	krb5_free_creds(context, ctx->kcred);
    if(ctx->source)
	krb5_free_principal (context, ctx->source);
    if(ctx->target)
	krb5_free_principal (context, ctx->target);
    if (ctx->ticket)
	krb5_free_ticket (context, ctx->ticket);
    if(ctx->order)
	_gssapi_msg_order_destroy(&ctx->order);
    if (ctx->service_keyblock)
	krb5_free_keyblock (context, ctx->service_keyblock);
    krb5_data_free(&ctx->fwd_data);
    if (ctx->crypto)
    	krb5_crypto_destroy(context, ctx->crypto);

    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
    HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex);
    memset(ctx, 0, sizeof(*ctx));
    free (ctx);
    return GSS_S_COMPLETE;
}
Beispiel #2
0
static int gensec_krb5_destroy(struct gensec_krb5_state *gensec_krb5_state)
{
	if (!gensec_krb5_state->smb_krb5_context) {
		/* We can't clean anything else up unless we started up this far */
		return 0;
	}
	if (gensec_krb5_state->enc_ticket.length) { 
		kerberos_free_data_contents(gensec_krb5_state->smb_krb5_context->krb5_context, 
					    &gensec_krb5_state->enc_ticket); 
	}

	if (gensec_krb5_state->ticket) {
		krb5_free_ticket(gensec_krb5_state->smb_krb5_context->krb5_context, 
				 gensec_krb5_state->ticket);
	}

	/* ccache freed in a child destructor */

	krb5_free_keyblock(gensec_krb5_state->smb_krb5_context->krb5_context, 
			   gensec_krb5_state->keyblock);
		
	if (gensec_krb5_state->auth_context) {
		krb5_auth_con_free(gensec_krb5_state->smb_krb5_context->krb5_context, 
				   gensec_krb5_state->auth_context);
	}

	return 0;
}
Condor_Auth_Kerberos :: ~Condor_Auth_Kerberos()
{
    if (krb_context_) {

        if (auth_context_) {
            krb5_auth_con_free(krb_context_, auth_context_);
        }

        if (krb_principal_) {
            krb5_free_principal(krb_context_, krb_principal_);
        }
        
        if (sessionKey_) {
            krb5_free_keyblock(krb_context_, sessionKey_);
        }
        
        if (server_) {
            krb5_free_principal(krb_context_, server_);
        }
        
        krb5_free_context(krb_context_);
    }
    
    if (defaultStash_) {
        free(defaultStash_);
        defaultStash_ = NULL;
    }

    if (ccname_) {
        free(ccname_);
        ccname_ = NULL;
    }
}
Beispiel #4
0
static void
ksm_decrement_ref_count(long msgid)
{
    struct ksm_cache_entry *entry, *entry1;
    int             bucket;

    bucket = msgid % HASHSIZE;

    if (ksm_hash_table[bucket] && ksm_hash_table[bucket]->msgid == msgid) {
        entry = ksm_hash_table[bucket];

        /*
         * If the reference count is zero, then free it
         */

        if (--entry->refcount <= 0) {
            DEBUGMSGTL(("ksm", "Freeing entry for msgid %ld\n", msgid));
            krb5_auth_con_free(kcontext, entry->auth_context);
            free(entry->secName);
            ksm_hash_table[bucket] = entry->next;
            free(entry);
        }

        return;

    } else if (ksm_hash_table[bucket])
        for (entry1 = ksm_hash_table[bucket], entry = entry1->next;
             entry != NULL; entry1 = entry, entry = entry->next)
            if (entry->msgid == msgid) {

                if (--entry->refcount <= 0) {
                    DEBUGMSGTL(("ksm", "Freeing entry for msgid %ld\n",
                                msgid));
                    krb5_auth_con_free(kcontext, entry->auth_context);
                    free(entry->secName);
                    entry1->next = entry->next;
                    free(entry);
                }

                return;
            }

    DEBUGMSGTL(("ksm",
                "KSM: Unable to decrement cache entry for msgid %ld.\n",
                msgid));
}
Beispiel #5
0
static krb5_error_code
fast_armor_ap_request(krb5_context context,
                      struct krb5int_fast_request_state *state,
                      krb5_ccache ccache, krb5_principal target_principal)
{
    krb5_error_code retval = 0;
    krb5_creds creds, *out_creds = NULL;
    krb5_auth_context authcontext = NULL;
    krb5_data encoded_authenticator;
    krb5_fast_armor *armor = NULL;
    krb5_keyblock *subkey = NULL, *armor_key = NULL;

    encoded_authenticator.data = NULL;
    memset(&creds, 0, sizeof(creds));
    creds.server = target_principal;
    retval = krb5_cc_get_principal(context, ccache, &creds.client);
    if (retval == 0)
        retval = krb5_get_credentials(context, 0, ccache,  &creds, &out_creds);
    if (retval == 0) {
        TRACE_FAST_ARMOR_CCACHE_KEY(context, &out_creds->keyblock);
        retval = krb5_mk_req_extended(context, &authcontext,
                                      AP_OPTS_USE_SUBKEY, NULL /*data*/,
                                      out_creds, &encoded_authenticator);
    }
    if (retval == 0)
        retval = krb5_auth_con_getsendsubkey(context, authcontext, &subkey);
    if (retval == 0)
        retval = krb5_c_fx_cf2_simple(context, subkey, "subkeyarmor",
                                      &out_creds->keyblock, "ticketarmor",
                                      &armor_key);
    if (retval == 0) {
        TRACE_FAST_ARMOR_KEY(context, armor_key);
        armor = calloc(1, sizeof(krb5_fast_armor));
        if (armor == NULL)
            retval = ENOMEM;
    }
    if (retval == 0) {
        armor->armor_type = KRB5_FAST_ARMOR_AP_REQUEST;
        armor->armor_value = encoded_authenticator;
        encoded_authenticator.data = NULL;
        encoded_authenticator.length = 0;
        state->armor = armor;
        armor = NULL;
        state->armor_key = armor_key;
        armor_key = NULL;
    }
    krb5_free_keyblock(context, armor_key);
    krb5_free_keyblock(context, subkey);
    if (out_creds)
        krb5_free_creds(context, out_creds);
    /* target_principal is owned by caller. */
    creds.server = NULL;
    krb5_free_cred_contents(context, &creds);
    if (encoded_authenticator.data)
        krb5_free_data_contents(context, &encoded_authenticator);
    krb5_auth_con_free(context, authcontext);
    return retval;
}
Beispiel #6
0
static krb5_error_code armor_ap_request
(struct kdc_request_state *state, krb5_fast_armor *armor)
{
    krb5_error_code retval = 0;
    krb5_auth_context authcontext = NULL;
    krb5_ticket *ticket = NULL;
    krb5_keyblock *subkey = NULL;
    kdc_realm_t *kdc_active_realm = state->realm_data;

    assert(armor->armor_type == KRB5_FAST_ARMOR_AP_REQUEST);
    krb5_clear_error_message(kdc_context);
    retval = krb5_auth_con_init(kdc_context, &authcontext);
    if (retval == 0)
        retval = krb5_auth_con_setflags(kdc_context,
                                        authcontext, 0); /*disable replay cache*/
    retval = krb5_rd_req(kdc_context, &authcontext,
                         &armor->armor_value, NULL /*server*/,
                         kdc_active_realm->realm_keytab,  NULL, &ticket);
    if (retval != 0) {
        const char * errmsg = krb5_get_error_message(kdc_context, retval);
        krb5_set_error_message(kdc_context, retval,
                               _("%s while handling ap-request armor"),
                               errmsg);
        krb5_free_error_message(kdc_context, errmsg);
    }
    if (retval == 0) {
        if (!krb5_principal_compare_any_realm(kdc_context,
                                              tgs_server,
                                              ticket->server)) {
            krb5_set_error_message(kdc_context, KRB5KDC_ERR_SERVER_NOMATCH,
                                   _("ap-request armor for something other "
                                     "than the local TGS"));
            retval = KRB5KDC_ERR_SERVER_NOMATCH;
        }
    }
    if (retval == 0) {
        retval = krb5_auth_con_getrecvsubkey(kdc_context, authcontext, &subkey);
        if (retval != 0 || subkey == NULL) {
            krb5_set_error_message(kdc_context, KRB5KDC_ERR_POLICY,
                                   _("ap-request armor without subkey"));
            retval = KRB5KDC_ERR_POLICY;
        }
    }
    if (retval == 0)
        retval = krb5_c_fx_cf2_simple(kdc_context,
                                      subkey, "subkeyarmor",
                                      ticket->enc_part2->session, "ticketarmor",
                                      &state->armor_key);
    if (ticket)
        krb5_free_ticket(kdc_context, ticket);
    if (subkey)
        krb5_free_keyblock(kdc_context, subkey);
    if (authcontext)
        krb5_auth_con_free(kdc_context, authcontext);
    return retval;
}
Beispiel #7
0
static void
ksm_free_state_ref(void *ptr)
{
    struct ksm_secStateRef *ref = (struct ksm_secStateRef *) ptr;

    DEBUGMSGTL(("ksm", "KSM: Freeing state reference\n"));

    krb5_auth_con_free(kcontext, ref->auth_context);

    free(ref);
}
Beispiel #8
0
kadm5_ret_t
kadm5_c_destroy(void *server_handle)
{
    kadm5_client_context *context = server_handle;

    free(context->realm);
    free(context->admin_server);
    close(context->sock);
    if (context->client_name)
	free(context->client_name);
    if (context->service_name)
	free(context->service_name);
    if (context->ac != NULL)
	krb5_auth_con_free(context->context, context->ac);
    if(context->my_context)
	krb5_free_context(context->context);
    return 0;
}
Beispiel #9
0
static void
remove_slave (krb5_context context, slave *s, slave **root)
{
    slave **p;

    if (s->fd >= 0)
	close (s->fd);
    if (s->name)
	free (s->name);
    if (s->ac)
	krb5_auth_con_free (context, s->ac);

    for (p = root; *p; p = &(*p)->next)
	if (*p == s) {
	    *p = s->next;
	    break;
	}
    free (s);
}
static void
remove_slave (krb5_context context, slave *s, slave **root)
{
    slave **p;

    if (!rk_IS_BAD_SOCKET(s->fd))
	rk_closesocket (s->fd);
    if (s->name)
	free (s->name);
    if (s->ac)
	krb5_auth_con_free (context, s->ac);

    for (p = root; *p; p = &(*p)->next)
	if (*p == s) {
	    *p = s->next;
	    break;
	}
    free (s);
}
Beispiel #11
0
void
kerberos5_is (TN_Authenticator * ap, unsigned char *data, int cnt)
{
  int r = 0;
  char errbuf[512];

  if (cnt-- < 1)
    return;
  errbuf[0] = 0;
  switch (*data++)
    {
    case KRB_AUTH:
      r = kerberos5_is_auth (ap, data, cnt, errbuf, sizeof errbuf);
      break;

    case KRB_FORWARD:
      r = kerberos5_is_forward (ap, data, cnt, errbuf, sizeof errbuf);
      break;

    default:
      DEBUG (("Unknown Kerberos option %d\r\n", data[-1]));
      Data (ap, KRB_REJECT, 0, 0);
      break;
    }

  if (r)
    {
      if (!errbuf[0])
	snprintf (errbuf, sizeof errbuf,
		  "kerberos_is: %s", error_message (r));
      Data (ap, KRB_REJECT, errbuf, -1);
      DEBUG (("%s\r\n", errbuf));
      syslog (LOG_ERR, "%s", errbuf);
      if (auth_context)
	{
	  krb5_auth_con_free (telnet_context, auth_context);
	  auth_context = 0;
	}
    }
}
Beispiel #12
0
void
krb5_cleanup_proc(Authctxt *authctxt)
{
	debug("krb5_cleanup_proc called");
	if (authctxt->krb5_fwd_ccache) {
		krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
		authctxt->krb5_fwd_ccache = NULL;
	}
	if (authctxt->krb5_user) {
		krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
		authctxt->krb5_user = NULL;
	}
	if (authctxt->krb5_auth_ctx) {
		krb5_auth_con_free(authctxt->krb5_ctx,
		    authctxt->krb5_auth_ctx);
		authctxt->krb5_auth_ctx = NULL;
	}
	if (authctxt->krb5_ctx) {
		krb5_free_context(authctxt->krb5_ctx);
		authctxt->krb5_ctx = NULL;
	}
}
krb5_error_code
_krb5_init_tgs_req(krb5_context context,
		   krb5_ccache ccache,
		   krb5_addresses *addresses,
		   krb5_kdc_flags flags,
		   krb5_const_principal impersonate_principal,
		   Ticket *second_ticket,
		   krb5_creds *in_creds,
		   krb5_creds *krbtgt,
		   unsigned nonce,
		   METHOD_DATA *padata,
		   krb5_keyblock **subkey,
		   TGS_REQ *t)
{
    krb5_auth_context ac = NULL;
    krb5_error_code ret = 0;
    
    /* inherit the forwardable/proxyable flags from the krbtgt */
    flags.b.forwardable = krbtgt->flags.b.forwardable;
    flags.b.proxiable = krbtgt->flags.b.proxiable;

    if (ccache->ops->tgt_req) {
	KERB_TGS_REQ_OUT out;
	KERB_TGS_REQ_IN in;
	
	memset(&in, 0, sizeof(in));
	memset(&out, 0, sizeof(out));

	ret = ccache->ops->tgt_req(context, ccache, &in, &out);
	if (ret)
	    return ret;

	free_KERB_TGS_REQ_OUT(&out);
	return 0;
    }


    memset(t, 0, sizeof(*t));

    if (impersonate_principal) {
	krb5_crypto crypto;
	PA_S4U2Self self;
	krb5_data data;
	void *buf;
	size_t size, len;

	self.name = impersonate_principal->name;
	self.realm = impersonate_principal->realm;
	self.auth = rk_UNCONST("Kerberos");
	
	ret = _krb5_s4u2self_to_checksumdata(context, &self, &data);
	if (ret)
	    goto fail;

	ret = krb5_crypto_init(context, &krbtgt->session, 0, &crypto);
	if (ret) {
	    krb5_data_free(&data);
	    goto fail;
	}

	ret = krb5_create_checksum(context,
				   crypto,
				   KRB5_KU_OTHER_CKSUM,
				   0,
				   data.data,
				   data.length,
				   &self.cksum);
	krb5_crypto_destroy(context, crypto);
	krb5_data_free(&data);
	if (ret)
	    goto fail;

	ASN1_MALLOC_ENCODE(PA_S4U2Self, buf, len, &self, &size, ret);
	free_Checksum(&self.cksum);
	if (ret)
	    goto fail;
	if (len != size)
	    krb5_abortx(context, "internal asn1 error");
	
	ret = krb5_padata_add(context, padata, KRB5_PADATA_FOR_USER, buf, len);
	if (ret)
	    goto fail;
    }

    t->pvno = 5;
    t->msg_type = krb_tgs_req;
    if (in_creds->session.keytype) {
	ALLOC_SEQ(&t->req_body.etype, 1);
	if(t->req_body.etype.val == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret,
				   N_("malloc: out of memory", ""));
	    goto fail;
	}
	t->req_body.etype.val[0] = in_creds->session.keytype;
    } else {
	ret = _krb5_init_etype(context,
			       KRB5_PDU_TGS_REQUEST,
			       &t->req_body.etype.len,
			       &t->req_body.etype.val,
			       NULL);
    }
    if (ret)
	goto fail;
    t->req_body.addresses = addresses;
    t->req_body.kdc_options = flags.b;
    ret = copy_Realm(&in_creds->server->realm, &t->req_body.realm);
    if (ret)
	goto fail;
    ALLOC(t->req_body.sname, 1);
    if (t->req_body.sname == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto fail;
    }

    /* some versions of some code might require that the client be
       present in TGS-REQs, but this is clearly against the spec */

    ret = copy_PrincipalName(&in_creds->server->name, t->req_body.sname);
    if (ret)
	goto fail;

    /* req_body.till should be NULL if there is no endtime specified,
       but old MIT code (like DCE secd) doesn't like that */
    ALLOC(t->req_body.till, 1);
    if(t->req_body.till == NULL){
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto fail;
    }
    *t->req_body.till = in_creds->times.endtime;

    t->req_body.nonce = nonce;
    if(second_ticket){
	ALLOC(t->req_body.additional_tickets, 1);
	if (t->req_body.additional_tickets == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret,
				   N_("malloc: out of memory", ""));
	    goto fail;
	}
	ALLOC_SEQ(t->req_body.additional_tickets, 1);
	if (t->req_body.additional_tickets->val == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret,
				   N_("malloc: out of memory", ""));
	    goto fail;
	}
	ret = copy_Ticket(second_ticket, t->req_body.additional_tickets->val);
	if (ret)
	    goto fail;
    }
    ALLOC(t->padata, 1);
    if (t->padata == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto fail;
    }
    ALLOC_SEQ(t->padata, 1 + padata->len);
    if (t->padata->val == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto fail;
    }
    {
	size_t i;
	for (i = 0; i < padata->len; i++) {
	    ret = copy_PA_DATA(&padata->val[i], &t->padata->val[i + 1]);
	    if (ret) {
		krb5_set_error_message(context, ret,
				       N_("malloc: out of memory", ""));
		goto fail;
	    }
	}
    }

    ret = krb5_auth_con_init(context, &ac);
    if(ret)
	goto fail;

    ret = krb5_auth_con_generatelocalsubkey(context, ac, &krbtgt->session);
    if (ret)
	goto fail;

    ret = set_auth_data (context, &t->req_body, &in_creds->authdata,
			 ac->local_subkey);
    if (ret)
	goto fail;

    ret = make_pa_tgs_req(context,
			  ac,
			  &t->req_body,
			  &t->padata->val[0],
			  ccache,
			  krbtgt);
    if(ret)
	goto fail;

    ret = krb5_auth_con_getlocalsubkey(context, ac, subkey);
    if (ret)
	goto fail;

fail:
    if (ac)
	krb5_auth_con_free(context, ac);
    if (ret) {
	t->req_body.addresses = NULL;
	free_TGS_REQ (t);
    }
    return ret;
}
Beispiel #14
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_auth_context auth_context;
    void *kadm_handle;
    kadm5_server_context *server_context;
    kadm5_config_params conf;
    int master_fd;
    krb5_ccache ccache;
    krb5_principal server;
    char **files;
    int optidx = 0;
    time_t reconnect_min;
    time_t backoff;
    time_t reconnect_max;
    time_t reconnect;
    time_t before = 0;

    const char *master;

    setprogname(argv[0]);

    if(getarg(args, num_args, argc, argv, &optidx))
	usage(1);

    if(help_flag)
	usage(0);
    if(version_flag) {
	print_version(NULL);
	exit(0);
    }

    ret = krb5_init_context(&context);
    if (ret)
	errx (1, "krb5_init_context failed: %d", ret);

    setup_signal();

    if (config_file == NULL) {
	asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context));
	if (config_file == NULL)
	    errx(1, "out of memory");
    }

    ret = krb5_prepend_config_files_default(config_file, &files);
    if (ret)
	krb5_err(context, 1, ret, "getting configuration files");

    ret = krb5_set_config_files(context, files);
    krb5_free_config_files(files);
    if (ret)
	krb5_err(context, 1, ret, "reading configuration files");

    argc -= optidx;
    argv += optidx;

    if (argc != 1)
	usage(1);

    master = argv[0];

#ifdef SUPPORT_DETACH
    if (detach_from_console)
	daemon(0, 0);
#endif
    pidfile (NULL);
    krb5_openlog (context, "ipropd-slave", &log_facility);
    krb5_set_warn_dest(context, log_facility);

    ret = krb5_kt_register(context, &hdb_kt_ops);
    if(ret)
	krb5_err(context, 1, ret, "krb5_kt_register");

    time_before_lost = parse_time (server_time_lost,  "s");
    if (time_before_lost < 0)
	krb5_errx (context, 1, "couldn't parse time: %s", server_time_lost);

    memset(&conf, 0, sizeof(conf));
    if(realm) {
	conf.mask |= KADM5_CONFIG_REALM;
	conf.realm = realm;
    }
    ret = kadm5_init_with_password_ctx (context,
					KADM5_ADMIN_SERVICE,
					NULL,
					KADM5_ADMIN_SERVICE,
					&conf, 0, 0,
					&kadm_handle);
    if (ret)
	krb5_err (context, 1, ret, "kadm5_init_with_password_ctx");

    server_context = (kadm5_server_context *)kadm_handle;

    ret = kadm5_log_init (server_context);
    if (ret)
	krb5_err (context, 1, ret, "kadm5_log_init");

    get_creds(context, keytab_str, &ccache, master);

    ret = krb5_sname_to_principal (context, master, IPROP_NAME,
				   KRB5_NT_SRV_HST, &server);
    if (ret)
	krb5_err (context, 1, ret, "krb5_sname_to_principal");

    auth_context = NULL;
    master_fd = -1;

    krb5_appdefault_time(context, config_name, NULL, "reconnect-min",
			 10, &reconnect_min);
    krb5_appdefault_time(context, config_name, NULL, "reconnect-max",
			 300, &reconnect_max);
    krb5_appdefault_time(context, config_name, NULL, "reconnect-backoff",
			 10, &backoff);
    reconnect = reconnect_min;

    while (!exit_flag) {
	time_t now, elapsed;
	int connected = FALSE;

	now = time(NULL);
	elapsed = now - before;

	if (elapsed < reconnect) {
	    time_t left = reconnect - elapsed;
	    krb5_warnx(context, "sleeping %d seconds before "
		       "retrying to connect", (int)left);
	    sleep(left);
	}
	before = now;

	master_fd = connect_to_master (context, master, port_str);
	if (master_fd < 0)
	    goto retry;

	reconnect = reconnect_min;

	if (auth_context) {
	    krb5_auth_con_free(context, auth_context);
	    auth_context = NULL;
	    krb5_cc_destroy(context, ccache);
	    get_creds(context, keytab_str, &ccache, master);
	}
	ret = krb5_sendauth (context, &auth_context, &master_fd,
			     IPROP_VERSION, NULL, server,
			     AP_OPTS_MUTUAL_REQUIRED, NULL, NULL,
			     ccache, NULL, NULL, NULL);
	if (ret) {
	    krb5_warn (context, ret, "krb5_sendauth");
	    goto retry;
	}

	krb5_warnx(context, "ipropd-slave started at version: %ld",
		   (long)server_context->log_context.version);

	ret = ihave (context, auth_context, master_fd,
		     server_context->log_context.version);
	if (ret)
	    goto retry;

	connected = TRUE;

	while (connected && !exit_flag) {
	    krb5_data out;
	    krb5_storage *sp;
	    int32_t tmp;
	    fd_set readset;
	    struct timeval to;

#ifndef NO_LIMIT_FD_SETSIZE
	    if (master_fd >= FD_SETSIZE)
		krb5_errx (context, 1, "fd too large");
#endif

	    FD_ZERO(&readset);
	    FD_SET(master_fd, &readset);

	    to.tv_sec = time_before_lost;
	    to.tv_usec = 0;

	    ret = select (master_fd + 1,
			  &readset, NULL, NULL, &to);
	    if (ret < 0) {
		if (errno == EINTR)
		    continue;
		else
		    krb5_err (context, 1, errno, "select");
	    }
	    if (ret == 0)
		krb5_errx (context, 1, "server didn't send a message "
			   "in %d seconds", time_before_lost);

	    ret = krb5_read_priv_message(context, auth_context, &master_fd, &out);
	    if (ret) {
		krb5_warn (context, ret, "krb5_read_priv_message");
		connected = FALSE;
		continue;
	    }

	    sp = krb5_storage_from_mem (out.data, out.length);
	    krb5_ret_int32 (sp, &tmp);
	    switch (tmp) {
	    case FOR_YOU :
		receive (context, sp, server_context);
		ret = ihave (context, auth_context, master_fd,
			     server_context->log_context.version);
		if (ret)
		    connected = FALSE;
		break;
	    case TELL_YOU_EVERYTHING :
		ret = receive_everything (context, master_fd, server_context,
					  auth_context);
		if (ret)
		    connected = FALSE;
		break;
	    case ARE_YOU_THERE :
		send_im_here (context, master_fd, auth_context);
		break;
	    case NOW_YOU_HAVE :
	    case I_HAVE :
	    case ONE_PRINC :
	    case I_AM_HERE :
	    default :
		krb5_warnx (context, "Ignoring command %d", tmp);
		break;
	    }
	    krb5_storage_free (sp);
	    krb5_data_free (&out);

	}
    retry:
	if (connected == FALSE)
	    krb5_warnx (context, "disconnected for server");
	if (exit_flag)
	    krb5_warnx (context, "got an exit signal");

	if (master_fd >= 0)
	    close(master_fd);

	reconnect += backoff;
	if (reconnect > reconnect_max)
	    reconnect = reconnect_max;
    }

    if (0);
#ifndef NO_SIGXCPU
    else if(exit_flag == SIGXCPU)
	krb5_warnx(context, "%s CPU time limit exceeded", getprogname());
#endif
    else if(exit_flag == SIGINT || exit_flag == SIGTERM)
	krb5_warnx(context, "%s terminated", getprogname());
    else
	krb5_warnx(context, "%s unexpected exit reason: %ld",
		       getprogname(), (long)exit_flag);
    
    return 0;
}
Beispiel #15
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;
}
Beispiel #16
0
static krb5_error_code
change_password_loop (krb5_context	context,
		      krb5_creds	*creds,
		      krb5_principal	targprinc,
		      char		*newpw,
		      int		*result_code,
		      krb5_data		*result_code_string,
		      krb5_data		*result_string,
		      struct kpwd_proc	*proc)
{
    krb5_error_code ret;
    krb5_auth_context auth_context = NULL;
    krb5_krbhst_handle handle = NULL;
    krb5_krbhst_info *hi;
    int sock;
    int i;
    int done = 0;
    krb5_realm realm = creds->client->realm;

    ret = krb5_auth_con_init (context, &auth_context);
    if (ret)
	return ret;

    krb5_auth_con_setflags (context, auth_context,
			    KRB5_AUTH_CONTEXT_DO_SEQUENCE);

    ret = krb5_krbhst_init (context, realm, KRB5_KRBHST_CHANGEPW, &handle);
    if (ret)
	goto out;

    while (!done && (ret = krb5_krbhst_next(context, handle, &hi)) == 0) {
	struct addrinfo *ai, *a;
	int is_stream;

	switch (hi->proto) {
	case KRB5_KRBHST_UDP:
	    if ((proc->flags & SUPPORT_UDP) == 0)
		continue;
	    is_stream = 0;
	    break;
	case KRB5_KRBHST_TCP:
	    if ((proc->flags & SUPPORT_TCP) == 0)
		continue;
	    is_stream = 1;
	    break;
	default:
	    continue;
	}

	ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
	if (ret)
	    continue;

	for (a = ai; !done && a != NULL; a = a->ai_next) {
	    int replied = 0;

	    sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
	    if (sock < 0)
		continue;

	    ret = connect(sock, a->ai_addr, a->ai_addrlen);
	    if (ret < 0) {
		close (sock);
		goto out;
	    }

	    ret = krb5_auth_con_genaddrs (context, auth_context, sock,
					  KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR);
	    if (ret) {
		close (sock);
		goto out;
	    }

	    for (i = 0; !done && i < 5; ++i) {
		fd_set fdset;
		struct timeval tv;

		if (!replied) {
		    replied = 0;
		    
		    ret = (*proc->send_req) (context,
					     &auth_context,
					     creds,
					     targprinc,
					     is_stream,
					     sock,
					     newpw,
					     hi->hostname);
		    if (ret) {
			close(sock);
			goto out;
		    }
		}
	    
		if (sock >= FD_SETSIZE) {
		    krb5_set_error_string(context, "fd %d too large", sock);
		    ret = ERANGE;
		    close (sock);
		    goto out;
		}

		FD_ZERO(&fdset);
		FD_SET(sock, &fdset);
		tv.tv_usec = 0;
		tv.tv_sec  = 1 + (1 << i);

		ret = select (sock + 1, &fdset, NULL, NULL, &tv);
		if (ret < 0 && errno != EINTR) {
		    close(sock);
		    goto out;
		}
		if (ret == 1) {
		    ret = (*proc->process_rep) (context,
						auth_context,
						is_stream,
						sock,
						result_code,
						result_code_string,
						result_string,
						hi->hostname);
		    if (ret == 0)
			done = 1;
		    else if (i > 0 && ret == KRB5KRB_AP_ERR_MUT_FAIL)
			replied = 1;
		} else {
		    ret = KRB5_KDC_UNREACH;
		}
	    }
	    close (sock);
	}
    }

 out:
    krb5_krbhst_free (context, handle);
    krb5_auth_con_free (context, auth_context);
    if (done)
	return 0;
    else {
	if (ret == KRB5_KDC_UNREACH) {
	    krb5_set_error_string(context,
				  "unable to reach any changepw server "
				  " in realm %s", realm);
	    *result_code = KRB5_KPASSWD_HARDERROR;
	}
	return ret;
    }
}
Beispiel #17
0
int auks_cred_init(auks_cred_t * credential, char *data, size_t length)
{
	int fstatus = AUKS_ERROR ;

	char *tmp_string = NULL;
	size_t tmp_size = 0;

	/* kerberos related variables */
	krb5_error_code err_code;
	krb5_context context;
	krb5_auth_context auth_context;
	krb5_data kdata;
	krb5_creds **creds;
	krb5_replay_data krdata;

	char username[AUKS_PRINCIPAL_MAX_LENGTH + 1];
	struct passwd user_pwent;
	struct passwd *p_pwent;
	size_t pwnam_buffer_length = sysconf(_SC_GETPW_R_SIZE_MAX);
	char pwnam_buffer[pwnam_buffer_length];

	credential->info.principal[0] = '\0';
	credential->info.uid = AUKS_CRED_INVALID_UID;

	credential->info.starttime = AUKS_CRED_INVALID_TIME;
	credential->info.endtime = AUKS_CRED_INVALID_TIME;
	credential->info.renew_till = AUKS_CRED_INVALID_TIME;

	credential->info.addressless = 1;

	credential->data[1] = '\0';
	credential->length = 0;
	credential->max_length = AUKS_CRED_DATA_MAX_LENGTH;
	credential->status = AUKS_SUCCESS;

	/* check input buffer length versus auks credential internal buffer */
	/* max length */
	if ((unsigned int) length > (unsigned int) credential->max_length) {
		auks_error("input buffer is bigger than auks credential internal "
			   "buffer (%u versus %u)",length, credential->max_length);
		fstatus = AUKS_ERROR_CRED_INIT_BUFFER_TOO_LARGE ;
		goto exit;
	}

	/* extract informations from buffer */
	if (data == NULL) {
		auks_error("input buffer is NULL");
		fstatus = AUKS_ERROR_CRED_INIT_BUFFER_IS_NULL ;
		goto exit;
	}
	fstatus = AUKS_ERROR ;

	/* initialize kerberos context */
	err_code = krb5_init_context(&context);
	if (err_code) {
		auks_error("unable to initialize kerberos context : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_CRED_INIT_KRB_CTX_INIT ;
		goto exit;
	}
	auks_log("kerberos context successfully initialized");

	/* initialize a nullified kerberos authentication context 
	   in order to decode credential from buffer */
	err_code =
		krb5_auth_con_init(context,&auth_context);
	if (err_code) {
		auks_error("unable to initialize connection "
			   "authentication context : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_CRED_INIT_KRB_AUTH_CTX_INIT ;
		goto ctx_exit;
	}
	
	/* clear kerberos authentication context flags */
	krb5_auth_con_setflags(context,auth_context,0);
	/* set a kerberos data structure with input buffer */
	kdata.data = data ;
	kdata.length = (unsigned int) length ;

	/* build kerberos credential structure using this data structure */
	err_code = krb5_rd_cred(context,auth_context,&kdata, &creds,&krdata);
	if (err_code) {
		auks_error("unable to deserialize input buffer credential : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_CRED_INIT_KRB_RD_BUFFER ;
		goto auth_ctx_exit;
	}

	auks_log("input buffer credential successfully unserialized");
	err_code = krb5_unparse_name_ext(context,(*creds)->client,&tmp_string,
					 (unsigned int *) &tmp_size);
	if (err_code) {
		auks_error("unable to unparse principal : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_CRED_INIT_KRB_RD_PRINC ;
		goto creds_exit;
	} else if (tmp_size > AUKS_PRINCIPAL_MAX_LENGTH) {
		auks_error("unable to unparse principal : %s",
			   "principal is too long (more than %d characters)",
			   AUKS_PRINCIPAL_MAX_LENGTH);
		free(tmp_string);
		fstatus = AUKS_ERROR_CRED_INIT_KRB_PRINC_TOO_LONG ;
		goto creds_exit;
	}
	auks_log("principal successfully unparse");
	memcpy(credential->info.principal,tmp_string,tmp_size);
	credential->info.principal[tmp_size] = '\0';
	/* associated username from principal */
	err_code = krb5_aname_to_localname(context,(*creds)->client,
					   AUKS_PRINCIPAL_MAX_LENGTH,username);
	if (err_code) {
		auks_error("unable to get username from principal %s : %s",
			   credential->info.principal,error_message(err_code));
		fstatus = AUKS_ERROR_CRED_INIT_KRB_PRINC_TO_UNAME ;
		goto string_exit;
	}

	/* associated uid from username */
	fstatus = getpwnam_r(username,&user_pwent,pwnam_buffer,
			     pwnam_buffer_length,&p_pwent) ;
	if (fstatus) {
		auks_log("unable to get %s pwnam entry : %s",username,
			 strerror(fstatus)) ;
		fstatus = AUKS_ERROR_CRED_INIT_GETPWNAM ;
		goto string_exit;
	}

	/* uid information */
	credential->info.uid = user_pwent.pw_uid;

	credential->info.starttime = (time_t) (*creds)->times.starttime ;
	credential->info.endtime = (time_t) (*creds)->times.endtime ;
	credential->info.renew_till = (time_t) (*creds)->times.renew_till ;

	/* addresslessness */
	if (((*creds)->addresses) != NULL)
		credential->info.addressless = 0;

	/* duplicate input buffer */
	credential->length = (unsigned int) length;
	memcpy(credential->data,data,(unsigned int) length);

	fstatus = AUKS_SUCCESS;

string_exit:
	free(tmp_string);

creds_exit:
	krb5_free_creds(context,*creds);
	free(creds);

auth_ctx_exit:
	krb5_auth_con_free(context,auth_context);

ctx_exit:
	krb5_free_context(context);

exit:
	/* if valid buffer, store it */
	if (fstatus != 0) {
		/* bad credential buffer in input, clean this auks credential */
		auks_cred_free_contents(credential);
	}
	
	return fstatus;
}
Beispiel #18
0
static int
proto (int sock, const char *hostname, const char *svc,
       char *message, size_t len)
{
    krb5_auth_context auth_context;
    krb5_error_code status;
    krb5_principal server;
    krb5_data data;
    krb5_data data_send;

    krb5_ccache     ccache;
    krb5_creds      creds;
    krb5_kdc_flags  flags;
    krb5_principal  principal;

    status = krb5_auth_con_init (context, &auth_context);
    if (status) {
	krb5_warn (context, status, "krb5_auth_con_init");
	return 1;
    }

    status = krb5_auth_con_setaddrs_from_fd (context,
					     auth_context,
					     &sock);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_auth_con_setaddr");
	return 1;
    }

    status = krb5_sname_to_principal (context,
				      hostname,
				      svc,
				      KRB5_NT_SRV_HST,
				      &server);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_sname_to_principal");
	return 1;
    }

    status = krb5_sendauth (context,
			    &auth_context,
			    &sock,
			    KF_VERSION_1,
			    NULL,
			    server,
			    AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
			    NULL,
			    NULL,
			    NULL,
			    NULL,
			    NULL,
			    NULL);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn(context, status, "krb5_sendauth");
	return 1;
    }

    if (ccache_name == NULL)
	ccache_name = "";

    data_send.data   = (void *)remote_name;
    data_send.length = strlen(remote_name) + 1;
    status = krb5_write_priv_message(context, auth_context, &sock, &data_send);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_write_message");
	return 1;
    }
    data_send.data   = (void *)ccache_name;
    data_send.length = strlen(ccache_name)+1;
    status = krb5_write_priv_message(context, auth_context, &sock, &data_send);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_write_message");
	return 1;
    }

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

    status = krb5_cc_default (context, &ccache);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_cc_default");
	return 1;
    }

    status = krb5_cc_get_principal (context, ccache, &principal);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_cc_get_principal");
	return 1;
    }

    creds.client = principal;

    status = krb5_make_principal (context,
				  &creds.server,
				  principal->realm,
				  KRB5_TGS_NAME,
				  principal->realm,
				  NULL);

    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_make_principal");
	return 1;
    }

    creds.times.endtime = 0;

    flags.i = 0;
    flags.b.forwarded   = 1;
    flags.b.forwardable = forwardable;

    status = krb5_get_forwarded_creds (context,
				       auth_context,
				       ccache,
				       flags.i,
				       hostname,
				       &creds,
				       &data);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_get_forwarded_creds");
	return 1;
    }

    status = krb5_write_priv_message(context, auth_context, &sock, &data);

    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_mk_priv");
	return 1;
    }

    krb5_data_free (&data);

    status = krb5_read_priv_message(context, auth_context, &sock, &data);
    krb5_auth_con_free(context, auth_context);
    if (status) {
	krb5_warn (context, status, "krb5_mk_priv");
	return 1;
    }
    if(data.length >= len) {
	krb5_warnx (context, "returned string is too long, truncating");
	memcpy(message, data.data, len);
	message[len - 1] = '\0';
    } else {
	memcpy(message, data.data, data.length);
	message[data.length] = '\0';
    }
    krb5_data_free (&data);

    return(strcmp(message, "ok"));
}
OM_uint32
gss_import_sec_context (
    OM_uint32 * minor_status,
    const gss_buffer_t interprocess_token,
    gss_ctx_id_t * context_handle
    )
{
    OM_uint32 ret = GSS_S_FAILURE;
    krb5_error_code kret;
    krb5_storage *sp;
    krb5_auth_context ac;
    krb5_address local, remote;
    krb5_address *localp, *remotep;
    krb5_data data;
    gss_buffer_desc buffer;
    krb5_keyblock keyblock;
    int32_t tmp;
    int32_t flags;
    OM_uint32 minor;
    int is_cfx = 0;

    GSSAPI_KRB5_INIT ();

    localp = remotep = NULL;

    sp = krb5_storage_from_mem (interprocess_token->value,
				interprocess_token->length);
    if (sp == NULL) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }

    *context_handle = malloc(sizeof(**context_handle));
    if (*context_handle == NULL) {
	*minor_status = ENOMEM;
	krb5_storage_free (sp);
	return GSS_S_FAILURE;
    }
    memset (*context_handle, 0, sizeof(**context_handle));
    HEIMDAL_MUTEX_init(&(*context_handle)->ctx_id_mutex);

    kret = krb5_auth_con_init (gssapi_krb5_context,
			       &(*context_handle)->auth_context);
    if (kret) {
	gssapi_krb5_set_error_string ();
	*minor_status = kret;
	ret = GSS_S_FAILURE;
	goto failure;
    }

    /* flags */

    *minor_status = 0;

    if (krb5_ret_int32 (sp, &flags) != 0)
	goto failure;

    /* retrieve the auth context */

    ac = (*context_handle)->auth_context;
    krb5_ret_int32 (sp, &ac->flags);
    if (flags & SC_LOCAL_ADDRESS) {
	if (krb5_ret_address (sp, localp = &local) != 0)
	    goto failure;
    }

    if (flags & SC_REMOTE_ADDRESS) {
	if (krb5_ret_address (sp, remotep = &remote) != 0)
	    goto failure;
    }

    krb5_auth_con_setaddrs (gssapi_krb5_context, ac, localp, remotep);
    if (localp)
	krb5_free_address (gssapi_krb5_context, localp);
    if (remotep)
	krb5_free_address (gssapi_krb5_context, remotep);
    localp = remotep = NULL;

    if (krb5_ret_int16 (sp, &ac->local_port) != 0)
	goto failure;

    if (krb5_ret_int16 (sp, &ac->remote_port) != 0)
	goto failure;
    if (flags & SC_KEYBLOCK) {
	if (krb5_ret_keyblock (sp, &keyblock) != 0)
	    goto failure;
	krb5_auth_con_setkey (gssapi_krb5_context, ac, &keyblock);
	krb5_free_keyblock_contents (gssapi_krb5_context, &keyblock);
    }
    if (flags & SC_LOCAL_SUBKEY) {
	if (krb5_ret_keyblock (sp, &keyblock) != 0)
	    goto failure;
	krb5_auth_con_setlocalsubkey (gssapi_krb5_context, ac, &keyblock);
	krb5_free_keyblock_contents (gssapi_krb5_context, &keyblock);
    }
    if (flags & SC_REMOTE_SUBKEY) {
	if (krb5_ret_keyblock (sp, &keyblock) != 0)
	    goto failure;
	krb5_auth_con_setremotesubkey (gssapi_krb5_context, ac, &keyblock);
	krb5_free_keyblock_contents (gssapi_krb5_context, &keyblock);
    }
    if (krb5_ret_int32 (sp, &ac->local_seqnumber))
	goto failure;
    if (krb5_ret_int32 (sp, &ac->remote_seqnumber))
	goto failure;

    if (krb5_ret_int32 (sp, &tmp) != 0)
	goto failure;
    ac->keytype = tmp;
    if (krb5_ret_int32 (sp, &tmp) != 0)
	goto failure;
    ac->cksumtype = tmp;

    /* names */

    if (krb5_ret_data (sp, &data))
	goto failure;
    buffer.value  = data.data;
    buffer.length = data.length;

    ret = gss_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME,
			   &(*context_handle)->source);
    if (ret) {
	ret = gss_import_name (minor_status, &buffer, GSS_C_NO_OID,
			       &(*context_handle)->source);
	if (ret) {
	    krb5_data_free (&data);
	    goto failure;
	}
    }
    krb5_data_free (&data);

    if (krb5_ret_data (sp, &data) != 0)
	goto failure;
    buffer.value  = data.data;
    buffer.length = data.length;

    ret = gss_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME,
			   &(*context_handle)->target);
    if (ret) {
	ret = gss_import_name (minor_status, &buffer, GSS_C_NO_OID,
			       &(*context_handle)->target);
	if (ret) {
	    krb5_data_free (&data);
	    goto failure;
	}
    }    
    krb5_data_free (&data);

    if (krb5_ret_int32 (sp, &tmp))
	goto failure;
    (*context_handle)->flags = tmp;
    if (krb5_ret_int32 (sp, &tmp))
	goto failure;
    (*context_handle)->more_flags = tmp;
    if (krb5_ret_int32 (sp, &tmp) == 0)
	(*context_handle)->lifetime = tmp;
    else
	(*context_handle)->lifetime = GSS_C_INDEFINITE;

    gsskrb5_is_cfx(*context_handle, &is_cfx);

    ret = _gssapi_msg_order_create(minor_status,
				   &(*context_handle)->order,
				   _gssapi_msg_order_f((*context_handle)->flags),
				   0, 0, is_cfx);
    if (ret)
	goto failure;

    krb5_storage_free (sp);
    return GSS_S_COMPLETE;

failure:
    krb5_auth_con_free (gssapi_krb5_context,
			(*context_handle)->auth_context);
    if ((*context_handle)->source != NULL)
	gss_release_name(&minor, &(*context_handle)->source);
    if ((*context_handle)->target != NULL)
	gss_release_name(&minor, &(*context_handle)->target);
    if (localp)
	krb5_free_address (gssapi_krb5_context, localp);
    if (remotep)
	krb5_free_address (gssapi_krb5_context, remotep);
    if((*context_handle)->order)
	_gssapi_msg_order_destroy(&(*context_handle)->order);
    HEIMDAL_MUTEX_destroy(&(*context_handle)->ctx_id_mutex);
    krb5_storage_free (sp);
    free (*context_handle);
    *context_handle = GSS_C_NO_CONTEXT;
    return ret;
}
Beispiel #20
0
/*
 * krb5_auth_context_internalize()	- Internalize the krb5_auth_context.
 */
static krb5_error_code
krb5_auth_context_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
{
    krb5_error_code	kret;
    krb5_auth_context	auth_context;
    krb5_int32		ibuf;
    krb5_octet		*bp;
    size_t		remain;
    krb5_int32		ivlen;
    krb5_int32		tag;

    bp = *buffer;
    remain = *lenremain;
    kret = EINVAL;
    /* Read our magic number */
    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
	ibuf = 0;
    if (ibuf == KV5M_AUTH_CONTEXT) {
	kret = ENOMEM;

	/* Get memory for the auth_context */
	if ((remain >= (5*sizeof(krb5_int32))) &&
	    (auth_context = (krb5_auth_context)
	     calloc(1, sizeof(struct _krb5_auth_context)))) {

	    /* Get auth_context_flags */
	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
	    auth_context->auth_context_flags = ibuf;

	    /* Get remote_seq_number */
	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
	    auth_context->remote_seq_number = ibuf;

	    /* Get local_seq_number */
	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
	    auth_context->local_seq_number = ibuf;

	    /* Get req_cksumtype */
	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
	    auth_context->req_cksumtype = (krb5_cksumtype) ibuf;

	    /* Get safe_cksumtype */
	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
	    auth_context->safe_cksumtype = (krb5_cksumtype) ibuf;

	    /* Get length of i_vector */
	    (void) krb5_ser_unpack_int32(&ivlen, &bp, &remain);

	    if (ivlen) {
		if ((auth_context->i_vector =
		     (krb5_pointer) malloc((size_t)ivlen)))
		    kret = krb5_ser_unpack_bytes(auth_context->i_vector,
						 (size_t) ivlen,
						 &bp,
						 &remain);
		else
		    kret = ENOMEM;
	    }
	    else
		kret = 0;
	    
	    /* Peek at next token */
	    tag = 0;
	    if (!kret)
		kret = krb5_ser_unpack_int32(&tag, &bp, &remain);

	    /* This is the remote_addr */
	    if (!kret && (tag == TOKEN_RADDR)) {
		if (!(kret = krb5_internalize_opaque(kcontext,
						     KV5M_ADDRESS,
						     (krb5_pointer *)
						     &auth_context->
						     remote_addr,
						     &bp,
						     &remain)))
		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
	    }

	    /* This is the remote_port */
	    if (!kret && (tag == TOKEN_RPORT)) {
		if (!(kret = krb5_internalize_opaque(kcontext,
						     KV5M_ADDRESS,
						     (krb5_pointer *)
						     &auth_context->
						     remote_port,
						     &bp,
						     &remain)))
		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
	    }

	    /* This is the local_addr */
	    if (!kret && (tag == TOKEN_LADDR)) {
		if (!(kret = krb5_internalize_opaque(kcontext,
						     KV5M_ADDRESS,
						     (krb5_pointer *)
						     &auth_context->
						     local_addr,
						     &bp,
						     &remain)))
		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
	    }

	    /* This is the local_port */
	    if (!kret && (tag == TOKEN_LPORT)) {
		if (!(kret = krb5_internalize_opaque(kcontext,
						     KV5M_ADDRESS,
						     (krb5_pointer *)
						     &auth_context->
						     local_port,
						     &bp,
						     &remain)))
		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
	    }

	    /* This is the keyblock */
	    if (!kret && (tag == TOKEN_KEYBLOCK)) {
		if (!(kret = krb5_internalize_opaque(kcontext,
						     KV5M_KEYBLOCK,
						     (krb5_pointer *)
						     &auth_context->keyblock,
						     &bp,
						     &remain)))
		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
	    }

	    /* This is the send_subkey */
	    if (!kret && (tag == TOKEN_LSKBLOCK)) {
		if (!(kret = krb5_internalize_opaque(kcontext,
						     KV5M_KEYBLOCK,
						     (krb5_pointer *)
						     &auth_context->
						     send_subkey,
						     &bp,
						     &remain)))
		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
	    }

	    /* This is the recv_subkey */
	    if (!kret) {
		if (tag == TOKEN_RSKBLOCK) {
		    kret = krb5_internalize_opaque(kcontext,
						   KV5M_KEYBLOCK,
						   (krb5_pointer *)
						   &auth_context->
						   recv_subkey,
						   &bp,
						   &remain);
		}
		else {
		    /*
		     * We read the next tag, but it's not of any use here, so
		     * we effectively 'unget' it here.
		     */
		    bp -= sizeof(krb5_int32);
		    remain += sizeof(krb5_int32);
		}
	    }

	    /* Now find the authentp */
	    if (!kret) {
		if ((kret = krb5_internalize_opaque(kcontext,
						    KV5M_AUTHENTICATOR,
						    (krb5_pointer *)
						    &auth_context->authentp,
						    &bp,
						    &remain))) {
		    if (kret == EINVAL)
			kret = 0;
		}
	    }

	    /* Finally, find the trailer */
	    if (!kret) {
		kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
		if (!kret && (ibuf != KV5M_AUTH_CONTEXT))
		    kret = EINVAL;
	    }
	    if (!kret) {
		*buffer = bp;
		*lenremain = remain;
		auth_context->magic = KV5M_AUTH_CONTEXT;
		*argp = (krb5_pointer) auth_context;
	    }
	    else
		krb5_auth_con_free(kcontext, auth_context);
	}
    }
    return(kret);
}
Beispiel #21
0
krb5_error_code KRB5_CALLCONV
krb5_verify_init_creds(krb5_context context,
                       krb5_creds *creds,
                       krb5_principal server_arg,
                       krb5_keytab keytab_arg,
                       krb5_ccache *ccache_arg,
                       krb5_verify_init_creds_opt *options)
{
    krb5_error_code ret;
    krb5_principal server;
    krb5_keytab keytab;
    krb5_ccache ccache;
    krb5_keytab_entry kte;
    krb5_creds in_creds, *out_creds;
    krb5_auth_context authcon;
    krb5_data ap_req;

    /* KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN */

    server = NULL;
    keytab = NULL;
    ccache = NULL;
    out_creds = NULL;
    authcon = NULL;
    ap_req.data = NULL;

    if (keytab_arg) {
        keytab = keytab_arg;
    } else {
        if ((ret = krb5_kt_default(context, &keytab)))
            goto cleanup;
    }

    if (server_arg) {
        ret = krb5_copy_principal(context, server_arg, &server);
        if (ret)
            goto cleanup;
    } else {
        /* Use a principal name from the keytab. */
        ret = k5_kt_get_principal(context, keytab, &server);
        if (ret) {
            /* There's no keytab, or it's empty, or we can't read it.
             * Allow this unless configuration demands verification. */
            if (!nofail(context, options, creds))
                ret = 0;
            goto cleanup;
        }
    }

    /* first, check if the server is in the keytab.  If not, there's
       no reason to continue.  rd_req does all this, but there's
       no way to know that a given error is caused by a missing
       keytab or key, and not by some other problem. */

    if (krb5_is_referral_realm(&server->realm)) {
        krb5_free_data_contents(context, &server->realm);
        ret = krb5_get_default_realm(context, &server->realm.data);
        if (ret) goto cleanup;
        server->realm.length = strlen(server->realm.data);
    }

    if ((ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte))) {
        /* this means there is no keying material.  This is ok, as long as
           it is not prohibited by the configuration */
        if (!nofail(context, options, creds))
            ret = 0;
        goto cleanup;
    }

    krb5_kt_free_entry(context, &kte);

    /* If the creds are for the server principal, we're set, just do a mk_req.
     * Otherwise, do a get_credentials first.
     */

    if (krb5_principal_compare(context, server, creds->server)) {
        /* make an ap_req */
        if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, creds,
                                        &ap_req)))
            goto cleanup;
    } else {
        /* this is unclean, but it's the easiest way without ripping the
           library into very small pieces.  store the client's initial cred
           in a memory ccache, then call the library.  Later, we'll copy
           everything except the initial cred into the ccache we return to
           the user.  A clean implementation would involve library
           internals with a coherent idea of "in" and "out". */

        /* insert the initial cred into the ccache */

        if ((ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) {
            ccache = NULL;
            goto cleanup;
        }

        if ((ret = krb5_cc_initialize(context, ccache, creds->client)))
            goto cleanup;

        if ((ret = krb5_cc_store_cred(context, ccache, creds)))
            goto cleanup;

        /* set up for get_creds */
        memset(&in_creds, 0, sizeof(in_creds));
        in_creds.client = creds->client;
        in_creds.server = server;
        if ((ret = krb5_timeofday(context, &in_creds.times.endtime)))
            goto cleanup;
        in_creds.times.endtime += 5*60;

        if ((ret = krb5_get_credentials(context, 0, ccache, &in_creds,
                                        &out_creds)))
            goto cleanup;

        /* make an ap_req */
        if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, out_creds,
                                        &ap_req)))
            goto cleanup;
    }

    /* wipe the auth context for mk_req */
    if (authcon) {
        krb5_auth_con_free(context, authcon);
        authcon = NULL;
    }

    /* verify the ap_req */

    if ((ret = krb5_rd_req(context, &authcon, &ap_req, server, keytab,
                           NULL, NULL)))
        goto cleanup;

    /* if we get this far, then the verification succeeded.  We can
       still fail if the library stuff here fails, but that's it */

    if (ccache_arg && ccache) {
        if (*ccache_arg == NULL) {
            krb5_ccache retcc;

            retcc = NULL;

            if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc)) ||
                (ret = krb5_cc_initialize(context, retcc, creds->client)) ||
                (ret = copy_creds_except(context, ccache, retcc,
                                         creds->server))) {
                if (retcc)
                    krb5_cc_destroy(context, retcc);
            } else {
                *ccache_arg = retcc;
            }
        } else {
            ret = copy_creds_except(context, ccache, *ccache_arg,
                                    server);
        }
    }

    /* if any of the above paths returned an errors, then ret is set accordingly.
     * Either that, or it's zero, which is fine, too
     */

cleanup:
    if ( server)
        krb5_free_principal(context, server);
    if (!keytab_arg && keytab)
        krb5_kt_close(context, keytab);
    if (ccache)
        krb5_cc_destroy(context, ccache);
    if (out_creds)
        krb5_free_creds(context, out_creds);
    if (authcon)
        krb5_auth_con_free(context, authcon);
    if (ap_req.data)
        free(ap_req.data);

    return(ret);
}
Beispiel #22
0
/*
 * pg_krb5_recvauth -- server routine to receive authentication information
 *					   from the client
 *
 * We still need to compare the username obtained from the client's setup
 * packet to the authenticated name, as described in pg_krb4_recvauth.	This
 * is a bit more problematic in v5, as described above in pg_an_to_ln.
 *
 * We have our own keytab file because postgres is unlikely to run as root,
 * and so cannot read the default keytab.
 */
static int
pg_krb5_recvauth(Port *port)
{
	krb5_error_code retval;
	int			ret;
	krb5_auth_context auth_context = NULL;
	krb5_ticket *ticket;
	char	   *kusername;

	ret = pg_krb5_init();
	if (ret != STATUS_OK)
		return ret;

	retval = krb5_recvauth(pg_krb5_context, &auth_context,
						   (krb5_pointer) & port->sock, PG_KRB_SRVNAM,
						   pg_krb5_server, 0, pg_krb5_keytab, &ticket);
	if (retval)
	{
		ereport(LOG,
				(errmsg("Kerberos recvauth returned error %d",
						retval)));
		com_err("postgres", retval, "from krb5_recvauth");
		return STATUS_ERROR;
	}

	/*
	 * The "client" structure comes out of the ticket and is therefore
	 * authenticated.  Use it to check the username obtained from the
	 * postmaster startup packet.
	 *
	 * I have no idea why this is considered necessary.
	 */
#if defined(HAVE_KRB5_TICKET_ENC_PART2)
	retval = krb5_unparse_name(pg_krb5_context,
							   ticket->enc_part2->client, &kusername);
#elif defined(HAVE_KRB5_TICKET_CLIENT)
	retval = krb5_unparse_name(pg_krb5_context,
							   ticket->client, &kusername);
#else
#error "bogus configuration"
#endif
	if (retval)
	{
		ereport(LOG,
				(errmsg("Kerberos unparse_name returned error %d",
						retval)));
		com_err("postgres", retval, "while unparsing client name");
		krb5_free_ticket(pg_krb5_context, ticket);
		krb5_auth_con_free(pg_krb5_context, auth_context);
		return STATUS_ERROR;
	}

	kusername = pg_an_to_ln(kusername);
	if (strncmp(port->user_name, kusername, SM_DATABASE_USER))
	{
		ereport(LOG,
				(errmsg("unexpected Kerberos user name received from client (received \"%s\", expected \"%s\")",
						port->user_name, kusername)));
		ret = STATUS_ERROR;
	}
	else
		ret = STATUS_OK;

	krb5_free_ticket(pg_krb5_context, ticket);
	krb5_auth_con_free(pg_krb5_context, auth_context);
	free(kusername);

	return ret;
}
Beispiel #23
0
static void
test_ap(krb5_context context,
	krb5_principal target,
	krb5_principal server,
	krb5_keytab keytab,
	krb5_ccache ccache,
	const krb5_flags client_flags)
{
    krb5_error_code ret;
    krb5_auth_context client_ac = NULL, server_ac = NULL;
    krb5_data data;
    krb5_flags server_flags;
    krb5_ticket *ticket = NULL;
    int32_t server_seq, client_seq;

    ret = krb5_mk_req_exact(context,
			    &client_ac,
			    client_flags,
			    target,
			    NULL,
			    ccache,
			    &data);
    if (ret)
	krb5_err(context, 1, ret, "krb5_mk_req_exact");

    ret = krb5_rd_req(context,
		      &server_ac,
		      &data,
		      server,
		      keytab,
		      &server_flags,
		      &ticket);
    if (ret)
	krb5_err(context, 1, ret, "krb5_rd_req");


    if (server_flags & AP_OPTS_MUTUAL_REQUIRED) {
	krb5_ap_rep_enc_part *repl;

	krb5_data_free(&data);

	if ((client_flags & AP_OPTS_MUTUAL_REQUIRED) == 0)
	    krb5_errx(context, 1, "client flag missing mutual req");

	ret = krb5_mk_rep (context, server_ac, &data);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_mk_rep");

	ret = krb5_rd_rep (context,
			   client_ac,
			   &data,
			   &repl);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_rd_rep");

	krb5_free_ap_rep_enc_part (context, repl);
    } else {
	if (client_flags & AP_OPTS_MUTUAL_REQUIRED)
	    krb5_errx(context, 1, "server flag missing mutual req");
    }

    krb5_auth_con_getremoteseqnumber(context, server_ac, &server_seq);
    krb5_auth_con_getremoteseqnumber(context, client_ac, &client_seq);
    if (server_seq != client_seq)
	krb5_errx(context, 1, "seq num differ");

    krb5_auth_con_getlocalseqnumber(context, server_ac, &server_seq);
    krb5_auth_con_getlocalseqnumber(context, client_ac, &client_seq);
    if (server_seq != client_seq)
	krb5_errx(context, 1, "seq num differ");

    krb5_data_free(&data);
    krb5_auth_con_free(context, client_ac);
    krb5_auth_con_free(context, server_ac);

    if (verify_pac) {
	krb5_pac pac;

	ret = krb5_ticket_get_authorization_data_type(context,
						      ticket,
						      KRB5_AUTHDATA_WIN2K_PAC,
						      &data);
	if (ret)
	    krb5_err(context, 1, ret, "get pac");

	ret = krb5_pac_parse(context, data.data, data.length, &pac);
	if (ret)
	    krb5_err(context, 1, ret, "pac parse");

	krb5_pac_free(context, pac);
    }

    krb5_free_ticket(context, ticket);
}
Beispiel #24
0
/**
 * @brief
 *		Get a kerberos credential set up to send to a remote host.
 *
 * @param[in]	remote	- server name
 * @param[in]	pjob	- pointer to job structure
 * @param[out]	data	- kerberos credential
 * @param[out]	dsize	- kerberos credential data length
 *
 * @return	int
 * @retval	0	- success
 * @retval	-1	- error
 */
static int
get_kerb_cred(char *remote, job *pjob, char **data, size_t *dsize)
{
	int			ret = -1;
#ifdef	PBS_CRED_DCE_KRB5
	krb5_error_code		err;
	int			got_auth = 0;
	char			server_name[512];
	char			namebuf[MAXPATHLEN+1];
	krb5_context		ktext = 0;
	krb5_auth_context	kauth = 0;
	krb5_ccache		kache = 0;
	krb5_principal		client = 0;
	krb5_principal		server = 0;
	krb5_data		forw_creds;
	krb5_data		packet;
	extern char		*path_jobs;

	DBPRT(("%s: entered %s\n", id, remote))
	memset(&forw_creds, 0, sizeof(forw_creds));
	memset(&packet, 0, sizeof(packet));

	if ((err = krb5_init_context(&ktext)) != 0) {
		sprintf(log_buffer,
			"krb5_init_context(%s)", error_message(err));
		log_err(-1, __func__, log_buffer);
		return ret;
	}

	if ((err = krb5_auth_con_init(ktext, &kauth)) != 0) {
		sprintf(log_buffer,
			"krb5_auth_con_init(%s)", error_message(err));
		log_err(-1, __func__, log_buffer);
		return ret;
	}
	got_auth = 1;

	krb5_auth_con_setflags(ktext, kauth, KRB5_AUTH_CONTEXT_RET_TIME);

	(void)strcpy(namebuf, path_jobs);
	if (*pjob->ji_qs.ji_fileprefix != '\0')
		(void)strcat(namebuf, pjob->ji_qs.ji_fileprefix);
	else
		(void)strcat(namebuf, pjob->ji_qs.ji_jobid);
	(void)strcat(namebuf, JOB_CRED_SUFFIX);
	if ((err = krb5_cc_resolve(ktext, namebuf, &kache)) != 0) {
		sprintf(log_buffer,
			"krb5_cc_resolve(%s)", error_message(err));
		log_err(-1, __func__, log_buffer);
		goto done;
	}

	if ((err = krb5_cc_get_principal(ktext, kache, &client)) != 0) {
		sprintf(log_buffer,
			"krb5_cc_get_principal(%s)", error_message(err));
		log_err(-1, __func__, log_buffer);
		goto done;
	}

	snprintf(server_name, sizeof(server_name), "host/%s@", remote);
	strncat(server_name, client->realm.data, client->realm.length);
	krb5_parse_name(ktext, server_name, &server);
	server->type = KRB5_NT_SRV_HST;

	if ((err = fwd_tgt_creds(ktext, kauth,
		client, server, kache, &forw_creds)) != 0) {
		sprintf(log_buffer, "no usable cred(%s)", error_message(err));
		log_err(-1, __func__, log_buffer);
		goto done;
	}

	*dsize = forw_creds.length;
	*data = forw_creds.data;
	ret = 0;

done:
	if (forw_creds.data && *data != forw_creds.data)
		free(forw_creds.data);
	if (client)
		krb5_free_principal(ktext, client);
	if (server)
		krb5_free_principal(ktext, server);
	if (got_auth)
		krb5_auth_con_free(ktext, kauth);
	krb5_free_context(ktext);
#endif	/* PBS_CRED_DCE_KRB5 */
	return ret;
}
Beispiel #25
0
/*
 * Function: socket_connection
 *
 * Purpose: Opens the network connection with the mail host, without
 * 	doing any sort of I/O with it or anything.
 *
 * Arguments:
 * 	host	The host to which to connect.
 *	flags	Option flags.
 *
 * Return value: A file descriptor indicating the connection, or -1
 * 	indicating failure, in which case an error has been copied
 * 	into pop_error.
 */
static int
socket_connection (char *host, int flags)
{
  struct addrinfo *res, *it;
  struct addrinfo hints;
  int ret;
  struct servent *servent;
  struct sockaddr_in addr;
  char found_port = 0;
  const char *service;
  int sock;
  char *realhost;
#ifdef KERBEROS
#ifdef KERBEROS5
  krb5_error_code rem;
  krb5_context kcontext = 0;
  krb5_auth_context auth_context = 0;
  krb5_ccache ccdef;
  krb5_principal client, server;
  krb5_error *err_ret;
  register char *cp;
#else
  KTEXT ticket;
  MSG_DAT msg_data;
  CREDENTIALS cred;
  Key_schedule schedule;
  int rem;
#endif /* KERBEROS5 */
#endif /* KERBEROS */

  int try_count = 0;
  int connect_ok;

#ifdef WINDOWSNT
  {
    WSADATA winsockData;
    if (WSAStartup (0x101, &winsockData) == 0)
      have_winsock = 1;
  }
#endif

  memset (&addr, 0, sizeof (addr));
  addr.sin_family = AF_INET;

  /** "kpop" service is  never used: look for 20060515 to see why **/
#ifdef KERBEROS
  service = (flags & POP_NO_KERBEROS) ? POP_SERVICE : KPOP_SERVICE;
#else
  service = POP_SERVICE;
#endif

#ifdef HESIOD
  if (! (flags & POP_NO_HESIOD))
    {
      servent = hes_getservbyname (service, "tcp");
      if (servent)
	{
	  addr.sin_port = servent->s_port;
	  found_port = 1;
	}
    }
#endif
  if (! found_port)
    {
      servent = getservbyname (service, "tcp");
      if (servent)
	{
	  addr.sin_port = servent->s_port;
	}
      else
	{
  /** "kpop" service is  never used: look for 20060515 to see why **/
#ifdef KERBEROS
	  addr.sin_port = htons ((flags & POP_NO_KERBEROS) ?
				POP_PORT : KPOP_PORT);
#else
	  addr.sin_port = htons (POP_PORT);
#endif
	}
    }

#define POP_SOCKET_ERROR "Could not create socket for POP connection: "

  sock = socket (PF_INET, SOCK_STREAM, 0);
  if (sock < 0)
    {
      snprintf (pop_error, ERROR_MAX, "%s%s",
		POP_SOCKET_ERROR, strerror (errno));
      return (-1);

    }

  memset (&hints, 0, sizeof (hints));
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_CANONNAME;
  hints.ai_family = AF_INET;
  do
    {
      ret = getaddrinfo (host, service, &hints, &res);
      try_count++;
      if (ret != 0 && (ret != EAI_AGAIN || try_count == 5))
	{
	  strcpy (pop_error, "Could not determine POP server's address");
	  return (-1);
	}
    } while (ret != 0);

  for (it = res; it; it = it->ai_next)
    if (it->ai_addrlen == sizeof addr)
      {
	struct sockaddr_in *in_a = (struct sockaddr_in *) it->ai_addr;
	addr.sin_addr = in_a->sin_addr;
	if (! connect (sock, (struct sockaddr *) &addr, sizeof addr))
	  break;
      }
  connect_ok = it != NULL;
  if (connect_ok)
    {
      realhost = alloca (strlen (it->ai_canonname) + 1);
      strcpy (realhost, it->ai_canonname);
    }
  freeaddrinfo (res);

#define CONNECT_ERROR "Could not connect to POP server: "

  if (! connect_ok)
    {
      CLOSESOCKET (sock);
      snprintf (pop_error, ERROR_MAX, "%s%s", CONNECT_ERROR, strerror (errno));
      return (-1);

    }

#ifdef KERBEROS

#define KRB_ERROR "Kerberos error connecting to POP server: "
  if (! (flags & POP_NO_KERBEROS))
    {
#ifdef KERBEROS5
      rem = krb5_init_context (&kcontext);
      if (rem)
	{
	krb5error:
	  if (auth_context)
	    krb5_auth_con_free (kcontext, auth_context);
	  if (kcontext)
	    krb5_free_context (kcontext);
	  snprintf (pop_error, ERROR_MAX, "%s%s",
		    KRB_ERROR, error_message (rem));
	  CLOSESOCKET (sock);
	  return (-1);
	}

      rem = krb5_auth_con_init (kcontext, &auth_context);
      if (rem)
	goto krb5error;

      rem = krb5_cc_default (kcontext, &ccdef);
      if (rem)
	goto krb5error;

      rem = krb5_cc_get_principal (kcontext, ccdef, &client);
      if (rem)
	goto krb5error;

      for (cp = realhost; *cp; cp++)
	*cp = c_tolower (*cp);

      rem = krb5_sname_to_principal (kcontext, realhost,
				     POP_SERVICE, FALSE, &server);
      if (rem)
	goto krb5error;

      rem = krb5_sendauth (kcontext, &auth_context,
			   (krb5_pointer) &sock, (char *) "KPOPV1.0",
			   client, server,
			  AP_OPTS_MUTUAL_REQUIRED,
			  0,	/* no checksum */
			  0,	/* no creds, use ccache instead */
			  ccdef,
			  &err_ret,
			  0,	/* don't need subsession key */
			  0);	/* don't need reply */
      krb5_free_principal (kcontext, server);
      if (rem)
	{
	  int pop_error_len = snprintf (pop_error, ERROR_MAX, "%s%s",
					KRB_ERROR, error_message (rem));
#if defined HAVE_KRB5_ERROR_TEXT
	  if (err_ret && err_ret->text.length)
	    {
	      int errlen = err_ret->text.length;
	      snprintf (pop_error + pop_error_len, ERROR_MAX - pop_error_len,
			" [server says '%.*s']", errlen, err_ret->text.data);
	    }
#elif defined HAVE_KRB5_ERROR_E_TEXT
	  if (err_ret && err_ret->e_text && **err_ret->e_text)
	    snprintf (pop_error + pop_error_len, ERROR_MAX - pop_error_len,
		      " [server says '%s']", *err_ret->e_text);
#endif
	  if (err_ret)
	    krb5_free_error (kcontext, err_ret);
	  krb5_auth_con_free (kcontext, auth_context);
	  krb5_free_context (kcontext);

	  CLOSESOCKET (sock);
	  return (-1);
	}
#else  /* ! KERBEROS5 */
      ticket = (KTEXT) malloc (sizeof (KTEXT_ST));
      rem = krb_sendauth (0L, sock, ticket, "pop", realhost,
			  (char *) krb_realmofhost (realhost),
			  (unsigned long) 0, &msg_data, &cred, schedule,
			  (struct sockaddr_in *) 0,
			  (struct sockaddr_in *) 0,
			  "KPOPV0.1");
      free ((char *) ticket);
      if (rem != KSUCCESS)
	{
	  snprintf (pop_error, ERROR_MAX, "%s%s", KRB_ERROR, krb_err_txt[rem]);
	  CLOSESOCKET (sock);
	  return (-1);
	}
#endif /* KERBEROS5 */
    }
#endif /* KERBEROS */

  return (sock);
} /* socket_connection */
Beispiel #26
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_verify_init_creds(krb5_context context,
		       krb5_creds *creds,
		       krb5_principal ap_req_server,
		       krb5_keytab ap_req_keytab,
		       krb5_ccache *ccache,
		       krb5_verify_init_creds_opt *options)
{
    krb5_error_code ret;
    krb5_data req;
    krb5_ccache local_ccache = NULL;
    krb5_creds *new_creds = NULL;
    krb5_auth_context auth_context = NULL;
    krb5_principal server = NULL;
    krb5_keytab keytab = NULL;

    krb5_data_zero (&req);

    if (ap_req_server == NULL) {
	char local_hostname[MAXHOSTNAMELEN];

	if (gethostname (local_hostname, sizeof(local_hostname)) < 0) {
	    ret = errno;
	    krb5_set_error_message (context, ret, "gethostname: %s",
				    strerror(ret));
	    return ret;
	}

	ret = krb5_sname_to_principal (context,
				       local_hostname,
				       "host",
				       KRB5_NT_SRV_HST,
				       &server);
	if (ret)
	    goto cleanup;
    } else
	server = ap_req_server;

    if (ap_req_keytab == NULL) {
	ret = krb5_kt_default (context, &keytab);
	if (ret)
	    goto cleanup;
    } else
	keytab = ap_req_keytab;

    if (ccache && *ccache)
	local_ccache = *ccache;
    else {
	ret = krb5_cc_new_unique(context, krb5_cc_type_memory,
				 NULL, &local_ccache);
	if (ret)
	    goto cleanup;
	ret = krb5_cc_initialize (context,
				  local_ccache,
				  creds->client);
	if (ret)
	    goto cleanup;
	ret = krb5_cc_store_cred (context,
				  local_ccache,
				  creds);
	if (ret)
	    goto cleanup;
    }

    if (!krb5_principal_compare (context, server, creds->server)) {
	krb5_creds match_cred;

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

	match_cred.client = creds->client;
	match_cred.server = server;

	ret = krb5_get_credentials (context,
				    0,
				    local_ccache,
				    &match_cred,
				    &new_creds);
	if (ret) {
	    if (fail_verify_is_ok (context, options))
		ret = 0;
	    goto cleanup;
	}
	creds = new_creds;
    }

    ret = krb5_mk_req_extended (context,
				&auth_context,
				0,
				NULL,
				creds,
				&req);

    krb5_auth_con_free (context, auth_context);
    auth_context = NULL;

    if (ret)
	goto cleanup;

    ret = krb5_rd_req (context,
		       &auth_context,
		       &req,
		       server,
		       keytab,
		       0,
		       NULL);

    if (ret == KRB5_KT_NOTFOUND && fail_verify_is_ok (context, options))
	ret = 0;
cleanup:
    if (auth_context)
	krb5_auth_con_free (context, auth_context);
    krb5_data_free (&req);
    if (new_creds != NULL)
	krb5_free_creds (context, new_creds);
    if (ap_req_server == NULL && server)
	krb5_free_principal (context, server);
    if (ap_req_keytab == NULL && keytab)
	krb5_kt_close (context, keytab);
    if (local_ccache != NULL
	&&
	(ccache == NULL
	 || (ret != 0 && *ccache == NULL)))
	krb5_cc_destroy (context, local_ccache);

    if (ret == 0 && ccache != NULL && *ccache == NULL)
	*ccache = local_ccache;

    return ret;
}
Beispiel #27
0
static krb5_error_code
tgs_parse_request(krb5_context context, 
		  krb5_kdc_configuration *config,
		  KDC_REQ_BODY *b,
		  const PA_DATA *tgs_req,
		  hdb_entry_ex **krbtgt,
		  krb5_enctype *krbtgt_etype,
		  krb5_ticket **ticket,
		  const char **e_text,
		  const char *from,
		  const struct sockaddr *from_addr,
		  time_t **csec,
		  int **cusec,
		  AuthorizationData **auth_data)
{
    krb5_ap_req ap_req;
    krb5_error_code ret;
    krb5_principal princ;
    krb5_auth_context ac = NULL;
    krb5_flags ap_req_options;
    krb5_flags verify_ap_req_flags;
    krb5_crypto crypto;
    Key *tkey;

    *auth_data = NULL;
    *csec  = NULL;
    *cusec = NULL;

    memset(&ap_req, 0, sizeof(ap_req));
    ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
    if(ret){
	kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", 
		krb5_get_err_text(context, ret));
	goto out;
    }

    if(!get_krbtgt_realm(&ap_req.ticket.sname)){
	/* XXX check for ticket.sname == req.sname */
	kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
	ret = KRB5KDC_ERR_POLICY; /* ? */
	goto out;
    }
    
    _krb5_principalname2krb5_principal(context,
				       &princ,
				       ap_req.ticket.sname,
				       ap_req.ticket.realm);
    
    ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, NULL, krbtgt);

    if(ret) {
	char *p;
	ret = krb5_unparse_name(context, princ, &p);
	if (ret != 0)
	    p = "<unparse_name failed>";
	krb5_free_principal(context, princ);
	kdc_log(context, config, 0,
		"Ticket-granting ticket not found in database: %s: %s",
		p, krb5_get_err_text(context, ret));
	if (ret == 0)
	    free(p);
	ret = KRB5KRB_AP_ERR_NOT_US;
	goto out;
    }
    
    if(ap_req.ticket.enc_part.kvno && 
       *ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){
	char *p;

	ret = krb5_unparse_name (context, princ, &p);
	krb5_free_principal(context, princ);
	if (ret != 0)
	    p = "<unparse_name failed>";
	kdc_log(context, config, 0,
		"Ticket kvno = %d, DB kvno = %d (%s)", 
		*ap_req.ticket.enc_part.kvno,
		(*krbtgt)->entry.kvno,
		p);
	if (ret == 0)
	    free (p);
	ret = KRB5KRB_AP_ERR_BADKEYVER;
	goto out;
    }

    *krbtgt_etype = ap_req.ticket.enc_part.etype;

    ret = hdb_enctype2key(context, &(*krbtgt)->entry, 
			  ap_req.ticket.enc_part.etype, &tkey);
    if(ret){
	char *str, *p;
	krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
	krb5_unparse_name(context, princ, &p);
	kdc_log(context, config, 0,
		"No server key with enctype %s found for %s", str, p);
	free(str);
	free(p);
	ret = KRB5KRB_AP_ERR_BADKEYVER;
	goto out;
    }
    
    if (b->kdc_options.validate)
	verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
    else
	verify_ap_req_flags = 0;

    ret = krb5_verify_ap_req2(context,
			      &ac,
			      &ap_req,
			      princ,
			      &tkey->key,
			      verify_ap_req_flags,
			      &ap_req_options,
			      ticket,
			      KRB5_KU_TGS_REQ_AUTH);
			     
    krb5_free_principal(context, princ);
    if(ret) {
	kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", 
		krb5_get_err_text(context, ret));
	goto out;
    }

    {
	krb5_authenticator auth;

	ret = krb5_auth_con_getauthenticator(context, ac, &auth);
	if (ret == 0) {
	    *csec   = malloc(sizeof(**csec));
	    if (*csec == NULL) {
		krb5_free_authenticator(context, &auth);
		kdc_log(context, config, 0, "malloc failed");
		goto out;
	    }
	    **csec  = auth->ctime;
	    *cusec  = malloc(sizeof(**cusec));
	    if (*cusec == NULL) {
		krb5_free_authenticator(context, &auth);
		kdc_log(context, config, 0, "malloc failed");
		goto out;
	    }
	    **cusec  = auth->cusec;
	    krb5_free_authenticator(context, &auth);
	}
    }

    ret = tgs_check_authenticator(context, config, 
				  ac, b, e_text, &(*ticket)->ticket.key);
    if (ret) {
	krb5_auth_con_free(context, ac);
	goto out;
    }

    if (b->enc_authorization_data) {
	krb5_keyblock *subkey;
	krb5_data ad;
	ret = krb5_auth_con_getremotesubkey(context,
					    ac,
					    &subkey);
	if(ret){
	    krb5_auth_con_free(context, ac);
	    kdc_log(context, config, 0, "Failed to get remote subkey: %s", 
		    krb5_get_err_text(context, ret));
	    goto out;
	}
	if(subkey == NULL){
	    ret = krb5_auth_con_getkey(context, ac, &subkey);
	    if(ret) {
		krb5_auth_con_free(context, ac);
		kdc_log(context, config, 0, "Failed to get session key: %s", 
			krb5_get_err_text(context, ret));
		goto out;
	    }
	}
	if(subkey == NULL){
	    krb5_auth_con_free(context, ac);
	    kdc_log(context, config, 0,
		    "Failed to get key for enc-authorization-data");
	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
	    goto out;
	}
	ret = krb5_crypto_init(context, subkey, 0, &crypto);
	if (ret) {
	    krb5_auth_con_free(context, ac);
	    kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
		    krb5_get_err_text(context, ret));
	    goto out;
	}
	ret = krb5_decrypt_EncryptedData (context,
					  crypto,
					  KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
					  b->enc_authorization_data,
					  &ad);
	krb5_crypto_destroy(context, crypto);
	if(ret){
	    krb5_auth_con_free(context, ac);
	    kdc_log(context, config, 0, 
		    "Failed to decrypt enc-authorization-data");
	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
	    goto out;
	}
	krb5_free_keyblock(context, subkey);
	ALLOC(*auth_data);
	if (*auth_data == NULL) {
	    krb5_auth_con_free(context, ac);
	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
	    goto out;
	}
	ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL);
	if(ret){
	    krb5_auth_con_free(context, ac);
	    free(*auth_data);
	    *auth_data = NULL;
	    kdc_log(context, config, 0, "Failed to decode authorization data");
	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
	    goto out;
	}
    }

    krb5_auth_con_free(context, ac);
    
out:
    free_AP_REQ(&ap_req);
    
    return ret;
}
Beispiel #28
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_verify_ap_req2(krb5_context context,
		    krb5_auth_context *auth_context,
		    krb5_ap_req *ap_req,
		    krb5_const_principal server,
		    krb5_keyblock *keyblock,
		    krb5_flags flags,
		    krb5_flags *ap_req_options,
		    krb5_ticket **ticket,
		    krb5_key_usage usage)
{
    krb5_ticket *t;
    krb5_auth_context ac;
    krb5_error_code ret;
    EtypeList etypes;

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

    if(ticket)
	*ticket = NULL;

    if (auth_context && *auth_context) {
	ac = *auth_context;
    } else {
	ret = krb5_auth_con_init(context, &ac);
	if (ret)
	    return ret;
    }

    t = calloc(1, sizeof(*t));
    if (t == NULL) {
	ret = ENOMEM;
	krb5_clear_error_message(context);
	goto out;
    }

    if (ap_req->ap_options.use_session_key && ac->keyblock){
	ret = krb5_decrypt_ticket(context, &ap_req->ticket,
				  ac->keyblock,
				  &t->ticket,
				  flags);
	krb5_free_keyblock(context, ac->keyblock);
	ac->keyblock = NULL;
    }else
	ret = krb5_decrypt_ticket(context, &ap_req->ticket,
				  keyblock,
				  &t->ticket,
				  flags);

    if(ret)
	goto out;

    ret = _krb5_principalname2krb5_principal(context,
					     &t->server,
					     ap_req->ticket.sname,
					     ap_req->ticket.realm);
    if (ret) goto out;
    ret = _krb5_principalname2krb5_principal(context,
					     &t->client,
					     t->ticket.cname,
					     t->ticket.crealm);
    if (ret) goto out;

    ret = decrypt_authenticator(context,
				&t->ticket.key,
				&ap_req->authenticator,
				ac->authenticator,
				usage);
    if (ret)
	goto out;

    {
	krb5_principal p1, p2;
	krb5_boolean res;

	_krb5_principalname2krb5_principal(context,
					   &p1,
					   ac->authenticator->cname,
					   ac->authenticator->crealm);
	_krb5_principalname2krb5_principal(context,
					   &p2,
					   t->ticket.cname,
					   t->ticket.crealm);
	res = krb5_principal_compare(context, p1, p2);
	krb5_free_principal(context, p1);
	krb5_free_principal(context, p2);
	if (!res) {
	    ret = KRB5KRB_AP_ERR_BADMATCH;
	    krb5_clear_error_message(context);
	    goto out;
	}
    }

    /* check addresses */

    if (t->ticket.caddr
	&& ac->remote_address
	&& !krb5_address_search(context,
				ac->remote_address,
				t->ticket.caddr)) {
	ret = KRB5KRB_AP_ERR_BADADDR;
	krb5_clear_error_message(context);
	goto out;
    }

    /* check timestamp in authenticator */
    {
	krb5_timestamp now;

	krb5_timeofday(context, &now);

	if (krb5_time_abs(ac->authenticator->ctime, now) > context->max_skew) {
	    ret = KRB5KRB_AP_ERR_SKEW;
	    krb5_clear_error_message(context);
	    goto out;
	}
    }

    if (ac->authenticator->seq_number)
	krb5_auth_con_setremoteseqnumber(context, ac,
					 *ac->authenticator->seq_number);

    /* XXX - Xor sequence numbers */

    if (ac->authenticator->subkey) {
	ret = krb5_auth_con_setremotesubkey(context, ac,
					    ac->authenticator->subkey);
	if (ret)
	    goto out;
    }

    ret = find_etypelist(context, ac, &etypes);
    if (ret)
	goto out;

    ac->keytype = (krb5_keytype)ETYPE_NULL;

    if (etypes.val) {
	size_t i;

	for (i = 0; i < etypes.len; i++) {
	    if (krb5_enctype_valid(context, etypes.val[i]) == 0) {
		ac->keytype = etypes.val[i];
		break;
	    }
	}
    }

    /* save key */
    ret = krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock);
    if (ret) goto out;

    if (ap_req_options) {
	*ap_req_options = 0;
	if (ac->keytype != ETYPE_NULL)
	    *ap_req_options |= AP_OPTS_USE_SUBKEY;
	if (ap_req->ap_options.use_session_key)
	    *ap_req_options |= AP_OPTS_USE_SESSION_KEY;
	if (ap_req->ap_options.mutual_required)
	    *ap_req_options |= AP_OPTS_MUTUAL_REQUIRED;
    }

    if(ticket)
	*ticket = t;
    else
	krb5_free_ticket(context, t);
    if (auth_context) {
	if (*auth_context == NULL)
	    *auth_context = ac;
    } else
	krb5_auth_con_free(context, ac);
    free_EtypeList(&etypes);
    return 0;
 out:
    free_EtypeList(&etypes);
    if (t)
	krb5_free_ticket(context, t);
    if (auth_context == NULL || *auth_context == NULL)
	krb5_auth_con_free(context, ac);
    return ret;
}
Beispiel #29
0
static krb5_error_code
init_tgs_req (krb5_context context,
	      krb5_ccache ccache,
	      krb5_addresses *addresses,
	      krb5_kdc_flags flags,
	      Ticket *second_ticket,
	      krb5_creds *in_creds,
	      krb5_creds *krbtgt,
	      unsigned nonce,
	      const METHOD_DATA *padata,
	      krb5_keyblock **subkey,
	      TGS_REQ *t)
{
    krb5_auth_context ac = NULL;
    krb5_error_code ret = 0;

    memset(t, 0, sizeof(*t));
    t->pvno = 5;
    t->msg_type = krb_tgs_req;
    if (in_creds->session.keytype) {
	ALLOC_SEQ(&t->req_body.etype, 1);
	if(t->req_body.etype.val == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret,
				   N_("malloc: out of memory", ""));
	    goto fail;
	}
	t->req_body.etype.val[0] = in_creds->session.keytype;
    } else {
	ret = krb5_init_etype(context,
			      &t->req_body.etype.len,
			      &t->req_body.etype.val,
			      NULL);
    }
    if (ret)
	goto fail;
    t->req_body.addresses = addresses;
    t->req_body.kdc_options = flags.b;
    ret = copy_Realm(&in_creds->server->realm, &t->req_body.realm);
    if (ret)
	goto fail;
    ALLOC(t->req_body.sname, 1);
    if (t->req_body.sname == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto fail;
    }

    /* some versions of some code might require that the client be
       present in TGS-REQs, but this is clearly against the spec */

    ret = copy_PrincipalName(&in_creds->server->name, t->req_body.sname);
    if (ret)
	goto fail;

    /* req_body.till should be NULL if there is no endtime specified,
       but old MIT code (like DCE secd) doesn't like that */
    ALLOC(t->req_body.till, 1);
    if(t->req_body.till == NULL){
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto fail;
    }
    *t->req_body.till = in_creds->times.endtime;

    t->req_body.nonce = nonce;
    if(second_ticket){
	ALLOC(t->req_body.additional_tickets, 1);
	if (t->req_body.additional_tickets == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret,
				   N_("malloc: out of memory", ""));
	    goto fail;
	}
	ALLOC_SEQ(t->req_body.additional_tickets, 1);
	if (t->req_body.additional_tickets->val == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret,
				   N_("malloc: out of memory", ""));
	    goto fail;
	}
	ret = copy_Ticket(second_ticket, t->req_body.additional_tickets->val);
	if (ret)
	    goto fail;
    }
    ALLOC(t->padata, 1);
    if (t->padata == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto fail;
    }
    ALLOC_SEQ(t->padata, 1 + padata->len);
    if (t->padata->val == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto fail;
    }
    {
	int i;
	for (i = 0; i < padata->len; i++) {
	    ret = copy_PA_DATA(&padata->val[i], &t->padata->val[i + 1]);
	    if (ret) {
		krb5_set_error_message(context, ret,
				       N_("malloc: out of memory", ""));
		goto fail;
	    }
	}
    }

    ret = krb5_auth_con_init(context, &ac);
    if(ret)
	goto fail;
    
    ret = krb5_auth_con_generatelocalsubkey(context, ac, &krbtgt->session);
    if (ret)
	goto fail;
    
    ret = set_auth_data (context, &t->req_body, &in_creds->authdata,
			 ac->local_subkey);
    if (ret)
	goto fail;
    
    ret = make_pa_tgs_req(context,
			  ac,
			  &t->req_body,
			  &t->padata->val[0],
			  krbtgt);
    if(ret)
	goto fail;

    ret = krb5_auth_con_getlocalsubkey(context, ac, subkey);
    if (ret)
	goto fail;

fail:
    if (ac)
	krb5_auth_con_free(context, ac);
    if (ret) {
	t->req_body.addresses = NULL;
	free_TGS_REQ (t);
    }
    return ret;
}
OM_uint32
_gsskrb5_create_ctx(
        OM_uint32 * minor_status,
	gss_ctx_id_t * context_handle,
 	const gss_channel_bindings_t input_chan_bindings,
 	enum gss_ctx_id_t_state state)
{
    krb5_error_code kret;
    gsskrb5_ctx ctx;

    *context_handle = NULL;

    ctx = malloc(sizeof(*ctx));
    if (ctx == NULL) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }
    ctx->auth_context		= NULL;
    ctx->source			= NULL;
    ctx->target			= NULL;
    ctx->state			= state;
    ctx->flags			= 0;
    ctx->more_flags		= 0;
    ctx->service_keyblock	= NULL;
    ctx->ticket			= NULL;
    krb5_data_zero(&ctx->fwd_data);
    ctx->lifetime		= GSS_C_INDEFINITE;
    ctx->order			= NULL;
    HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex);

    kret = krb5_auth_con_init (_gsskrb5_context, &ctx->auth_context);
    if (kret) {
	*minor_status = kret;
	_gsskrb5_set_error_string ();

	HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex);
		
	return GSS_S_FAILURE;
    }

    kret = set_addresses(ctx->auth_context, input_chan_bindings);
    if (kret) {
	*minor_status = kret;

	HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex);

	krb5_auth_con_free(_gsskrb5_context, ctx->auth_context);

	return GSS_S_BAD_BINDINGS;
    }

    /*
     * We need a sequence number
     */

    krb5_auth_con_addflags(_gsskrb5_context,
			   ctx->auth_context,
			   KRB5_AUTH_CONTEXT_DO_SEQUENCE |
			   KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED,
			   NULL);

    *context_handle = (gss_ctx_id_t)ctx;

    return GSS_S_COMPLETE;
}