static krb5_error_code
kcm_get_uuid(krb5_context context, krb5_ccache id, krb5_uuid uuid)
{
    krb5_storage *request, *response;
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_data response_data;
    krb5_error_code ret;
    ssize_t sret;
    
    ret = krb5_kcm_storage_request(context, KCM_OP_GET_UUID, &request);
    if (ret)
	return ret;

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, &response, &response_data);
    krb5_storage_free(request);
    if (ret)
	return ret;
    
    sret = krb5_storage_read(response, uuid, sizeof(krb5_uuid));
    krb5_storage_free(response);
    if (sret != sizeof(krb5_uuid))
	return KRB5_CC_IO;
    
    return 0;
}
static krb5_error_code
kcm_get_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat *kdc_offset)
{
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_error_code ret;
    krb5_storage *request, *response;
    krb5_data response_data;
    int32_t offset;

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, &response, &response_data);
    krb5_storage_free(request);
    if (ret)
	return ret;

    ret = krb5_ret_int32(response, &offset);
    krb5_storage_free(response);
    krb5_data_free(&response_data);
    if (ret)
	return ret;

    *kdc_offset = offset;

    return 0;
}
/*
 * Request:
 *      NameZ
 *      Creds
 *
 * Response:
 *
 */
static krb5_error_code
kcm_store_cred(krb5_context context,
	       krb5_ccache id,
	       krb5_creds *creds)
{
    krb5_error_code ret;
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_storage *request;

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_creds(request, creds);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);

    krb5_storage_free(request);
    return ret;
}
/*
 * Request:
 *      NameZ
 *      Principal
 *
 * Response:
 *
 */
static krb5_error_code
kcm_initialize(krb5_context context,
	       krb5_ccache id,
	       krb5_principal primary_principal)
{
    krb5_error_code ret;
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_storage *request;

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_principal(request, primary_principal);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);

    krb5_storage_free(request);

    if (context->kdc_sec_offset)
	kcm_set_kdc_offset(context, id, context->kdc_sec_offset);

    return ret;
}
static krb5_error_code
kcm_set_flags(krb5_context context,
	      krb5_ccache id,
	      krb5_flags flags)
{
    krb5_error_code ret;
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_storage *request;

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_int32(request, flags);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);

    krb5_storage_free(request);
    return ret;
}
static krb5_error_code
kcm_move(krb5_context context, krb5_ccache from, krb5_ccache to)
{
    krb5_error_code ret;
    krb5_kcmcache *oldk = KCMCACHE(from);
    krb5_kcmcache *newk = KCMCACHE(to);
    krb5_storage *request;

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

    ret = krb5_store_stringz(request, oldk->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_stringz(request, newk->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }
    ret = krb5_kcm_call(context, request, NULL, NULL);

    krb5_storage_free(request);
    return ret;
}
static krb5_error_code
kcm_get_default_name(krb5_context context, const krb5_cc_ops *ops,
		     const char *defstr, char **str)
{
    krb5_error_code ret;
    krb5_storage *request, *response;
    krb5_data response_data;
    char *name;

    *str = NULL;

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

    ret = krb5_kcm_call(context, request, &response, &response_data);
    krb5_storage_free(request);
    if (ret)
	return _krb5_expand_default_cc_name(context, defstr, str);

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

    asprintf(str, "%s:%s", ops->prefix, name);
    free(name);
    if (str == NULL)
	return ENOMEM;

    return 0;
}
static krb5_error_code
kcm_set_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat kdc_offset)
{
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_error_code ret;
    krb5_storage *request;

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }
    ret = krb5_store_int32(request, (uint32_t)kdc_offset);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);
    krb5_storage_free(request);

    return ret;
}
static int
calculate(void *ptr,
	  heim_scram_method method,
	  unsigned int iterations,
	  heim_scram_data *salt,
	  const heim_scram_data *c1,
	  const heim_scram_data *s1,
	  const heim_scram_data *c2noproof,
	  heim_scram_data *proof,
	  heim_scram_data *server,
	  heim_scram_data *sessionKey)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_storage *request, *response = NULL;
    krb5_data response_data;
    scram_id_t ctx = ptr;

    ret = krb5_init_context(&context);
    if (ret) {
	return ret;
    }
    ret = krb5_kcm_storage_request(context, KCM_OP_DO_SCRAM_AUTH, &request);
    if (ret) {
	krb5_free_context(context);
	return GSS_S_FAILURE;
    }
    ret = krb5_store_stringz(request, ctx->client);
    if (ret == 0)
	ret = krb5_store_uint32(request, iterations);
    if (ret == 0)
	ret = krb5_store_data(request, *salt);
    if (ret == 0)
	ret = krb5_store_data(request, *c1);
    if (ret == 0)
	ret = krb5_store_data(request, *s1);
    if (ret == 0)
	ret = krb5_store_data(request, *c2noproof);
    if (ret == 0)
	ret = krb5_kcm_call(context, request, &response, &response_data);
    
    krb5_free_context(context);
    krb5_storage_free(request);
    if (ret == 0)
    ret = krb5_ret_data(response, proof);
    if (ret == 0)
	ret = krb5_ret_data(response, server);
    if (ret == 0)
	ret = krb5_ret_data(response, sessionKey);
    if (ret)
	ret = KRB5_CC_IO;
    
    if (response)
	krb5_storage_free(response);
    krb5_data_free(&response_data);

    return ret;
    
}
/*
 * Request:
 *      NameZ
 *
 * Request:
 *      NameZ
 *      ClientPrincipal
 *      ServerPrincipalPresent
 *      ServerPrincipal OPTIONAL
 *      Password
 *
 * Repsonse:
 *
 */
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_kcm_get_initial_ticket(krb5_context context,
			     krb5_ccache id,
			     krb5_principal client,
			     krb5_principal server,
			     const char *password)
{
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_error_code ret;
    krb5_storage *request;

    if (id->ops != &krb5_kcm_ops && id->ops != &krb5_akcm_ops) {
	krb5_set_error_message(context, EINVAL, "Cache is not a KCM cache");
	return EINVAL;
    }

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_principal(request, client);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_int8(request, (server == NULL) ? 0 : 1);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    if (server != NULL) {
	ret = krb5_store_principal(request, server);
	if (ret) {
	    krb5_storage_free(request);
	    return ret;
	}
    }

    ret = krb5_store_stringz(request, password);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);
    krb5_storage_free(request);

    return ret;
}
/*
 * Request:
 *      NameZ
 *      Cursor
 *
 * Response:
 *      Creds
 */
static krb5_error_code
kcm_get_next (krb5_context context,
		krb5_ccache id,
		krb5_cc_cursor *cursor,
		krb5_creds *creds)
{
    krb5_error_code ret;
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_kcm_cursor c = KCMCURSOR(*cursor);
    krb5_storage *request, *response;
    krb5_data response_data;
    ssize_t sret;

 again:

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

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	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_CC_END) {
	goto again;
    } else if (ret)
	return ret;

    ret = krb5_ret_creds(response, creds);
    if (ret)
	ret = KRB5_CC_IO;

    krb5_storage_free(response);
    krb5_data_free(&response_data);

    return ret;
}
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;
}
void
_gss_scram_iter_creds_f(OM_uint32 flags,
		       void *userctx ,
		       void (*cred_iter)(void *, gss_OID, gss_cred_id_t))
{
    krb5_error_code ret;
    krb5_context context = NULL;
    krb5_storage *request, *response;
    krb5_data response_data;
    
    ret = krb5_init_context(&context);
    if (ret)
	goto done;

    ret = krb5_kcm_storage_request(context, KCM_OP_GET_SCRAM_USER_LIST, &request);
    if (ret)
	goto done;

    ret = krb5_kcm_call(context, request, &response, &response_data);
    krb5_storage_free(request);
    if (ret)
	goto done;

    while (1) {
	uint32_t morep;
	kcmuuid_t uuid;
	char *user = NULL;
	krb5_ssize_t sret;

	ret = krb5_ret_uint32(response, &morep);
	if (ret) goto out;

	if (!morep) goto out;

	ret = krb5_ret_stringz(response, &user);
	if (ret) goto out;

	sret = krb5_storage_read(response, uuid, sizeof(uuid));
	if (sret != sizeof(uuid))
	    goto out;

	    cred_iter(userctx, GSS_SCRAM_MECHANISM, (gss_cred_id_t)user);
    }
 out:
    krb5_storage_free(response);
    krb5_data_free(&response_data);
 done:
    if (context)
	krb5_free_context(context);
    (*cred_iter)(userctx, NULL, NULL);
}		 
/*
 * Request:
 *      NameZ
 *      WhichFields
 *      MatchCreds
 *
 * Response:
 *      Creds
 *
 */
static krb5_error_code
kcm_retrieve(krb5_context context,
	     krb5_ccache id,
	     krb5_flags which,
	     const krb5_creds *mcred,
	     krb5_creds *creds)
{
    krb5_error_code ret;
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_storage *request, *response;
    krb5_data response_data;

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_int32(request, which);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_creds_tag(request, rk_UNCONST(mcred));
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, &response, &response_data);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_ret_creds(response, creds);
    if (ret)
	ret = KRB5_CC_IO;

    krb5_storage_free(request);
    krb5_storage_free(response);
    krb5_data_free(&response_data);

    return ret;
}
Exemple #15
0
OM_uint32
_gss_scram_have_cred(OM_uint32 *minor,
		     const char *name,
		     gss_cred_id_t *rcred)
{
    krb5_context context;
    krb5_error_code ret;
    krb5_storage *request = NULL, *response;
    krb5_data response_data;
    OM_uint32 major;

    ret = krb5_init_context(&context);
    if (ret) {
	*minor = ret;
	return GSS_S_FAILURE;
    }

    ret = krb5_kcm_storage_request(context, KCM_OP_HAVE_SCRAM_CRED, &request);
    if (ret)
	goto out;

    ret = krb5_store_stringz(request, name);
    if (ret)
	goto out;

    ret = krb5_kcm_call(context, request, &response, &response_data);
    if (ret)
	goto out;

    request = NULL;

    if (rcred) {
        *rcred = (gss_cred_id_t)strdup(name);
	if (*rcred == NULL)
	    ret = ENOMEM;
    }
 out:
    if (request)
	krb5_storage_free(request);
    krb5_free_context(context);
    if (ret) {
	*minor = ret;
	major = GSS_S_FAILURE;
    } else
	major = GSS_S_COMPLETE;

    return major;
}
/*
 * Request:
 *
 * Response:
 *
 */
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_kcm_noop(krb5_context context,
	       krb5_ccache id)
{
    krb5_error_code ret;
    krb5_storage *request;

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

    ret = krb5_kcm_call(context, request, NULL, NULL);
    krb5_storage_free(request);

    return ret;
}
Exemple #17
0
/*
 * Request:
 *      NameZ
 *      ServerPrincipalPresent
 *      ServerPrincipal OPTIONAL
 *      Key
 *
 * Repsonse:
 *
 */
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_kcm_get_initial_ticket(krb5_context context,
			     krb5_ccache id,
			     krb5_principal server,
			     krb5_keyblock *key)
{
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_error_code ret;
    krb5_storage *request;

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_int8(request, (server == NULL) ? 0 : 1);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    if (server != NULL) {
	ret = krb5_store_principal(request, server);
	if (ret) {
	    krb5_storage_free(request);
	    return ret;
	}
    }

    ret = krb5_store_keyblock(request, *key);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);

    krb5_storage_free(request);
    return ret;
}
/*
 * Request:
 *      NameZ
 *      KDCFlags
 *      EncryptionType
 *      ServerPrincipal
 *
 * Repsonse:
 *
 */
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_kcm_get_ticket(krb5_context context,
		     krb5_ccache id,
		     krb5_kdc_flags flags,
		     krb5_enctype enctype,
		     krb5_principal server)
{
    krb5_error_code ret;
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_storage *request;

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_int32(request, flags.i);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_int32(request, enctype);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_principal(request, server);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);
    krb5_storage_free(request);

    return ret;
}
Exemple #19
0
/*
 * Request:
 *
 * Response:
 *      NameZ
 */
static krb5_error_code
kcm_gen_new(krb5_context context, krb5_ccache *id)
{
    krb5_kcmcache *k;
    krb5_error_code ret;
    krb5_storage *request, *response;
    krb5_data response_data;

    ret = kcm_alloc(context, NULL, id);
    if (ret)
	return ret;

    k = KCMCACHE(*id);

    ret = krb5_kcm_storage_request(context, KCM_OP_GEN_NEW, &request);
    if (ret) {
	kcm_free(context, id);
	return ret;
    }

    ret = krb5_kcm_call(context, request, &response, &response_data);
    if (ret) {
	krb5_storage_free(request);
	kcm_free(context, id);
	return ret;
    }

    ret = krb5_ret_stringz(response, &k->name);
    if (ret)
	ret = KRB5_CC_IO;

    krb5_storage_free(request);
    krb5_storage_free(response);
    krb5_data_free(&response_data);

    if (ret)
	kcm_free(context, id);

    return ret;
}
Exemple #20
0
static OM_uint32
_gss_ntlm_destroy_kcm_cred(gss_cred_id_t *cred_handle)
{
    krb5_storage *request, *response;
    krb5_data response_data;
    krb5_context context;
    krb5_error_code ret;
    ntlm_cred cred;

    cred = (ntlm_cred)*cred_handle;

    ret = krb5_init_context(&context);
    if (ret)
        return ret;

    ret = krb5_kcm_storage_request(context, KCM_OP_DEL_NTLM_CRED, &request);
    if (ret)
	goto out;

    ret = krb5_store_stringz(request, cred->username);
    if (ret)
	goto out;

    ret = krb5_store_stringz(request, cred->domain);
    if (ret)
	goto out;

    ret = krb5_kcm_call(context, request, &response, &response_data);
    if (ret)
	goto out;

    krb5_storage_free(request);
    krb5_storage_free(response);
    krb5_data_free(&response_data);

 out:
    krb5_free_context(context);

    return ret;
}
static krb5_error_code
kcm_set_default(krb5_context context, krb5_ccache id)
{
    krb5_error_code ret;
    krb5_storage *request;
    krb5_kcmcache *k = KCMCACHE(id);

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);
    krb5_storage_free(request);

    return ret;
}
static krb5_error_code
kcm_unhold(krb5_context context, krb5_ccache id)
{
    krb5_storage *request;
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_error_code ret;
    
    ret = krb5_kcm_storage_request(context, KCM_OP_RELEASE_KCRED, &request);
    if (ret)
	return ret;

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);
    krb5_storage_free(request);

    return ret;
}
/*
 * Request:
 *      NameZ
 *      WhichFields
 *      MatchCreds
 *
 * Response:
 *
 */
static krb5_error_code
kcm_remove_cred(krb5_context context,
		krb5_ccache id,
		krb5_flags which,
		krb5_creds *cred)
{
    krb5_error_code ret;
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_storage *request;

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_int32(request, which);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_creds_tag(request, cred);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);

    krb5_storage_free(request);
    return ret;
}
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;
}
/*
 * Request:
 *      NameZ
 *
 * Response:
 *      Principal
 */
static krb5_error_code
kcm_get_principal(krb5_context context,
		  krb5_ccache id,
		  krb5_principal *principal)
{
    krb5_error_code ret;
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_storage *request, *response;
    krb5_data response_data;

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

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, &response, &response_data);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_ret_principal(response, principal);
    if (ret)
	ret = KRB5_CC_IO;

    krb5_storage_free(request);
    krb5_storage_free(response);
    krb5_data_free(&response_data);

    return ret;
}
/*
 * Request:
 *
 * Response:
 *
 */
krb5_error_code
_krb5_kcm_ntlm_challenge(krb5_context context, int op __attribute((__unused__)),
			 uint8_t chal[8])
{
    krb5_error_code ret;
    krb5_ssize_t sret;
    krb5_storage *request;

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

    sret = krb5_storage_write(request, chal, 8);
    if (sret != 8) {
	ret = EINVAL;
	goto out;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);

 out:
    krb5_storage_free(request);
    return ret;
}
OM_uint32
_gss_ntlm_acquire_cred_ext(OM_uint32 * minor_status,
			   const gss_name_t desired_name,
			   gss_const_OID credential_type,
			   const void *credential_data,
			   OM_uint32 time_req,
			   gss_const_OID desired_mech,
			   gss_cred_usage_t cred_usage,
			   gss_cred_id_t * output_cred_handle)
{
    ntlm_name name = (ntlm_name) desired_name;
    OM_uint32 major;
    krb5_storage *request, *response;
    krb5_data response_data;
    krb5_context context;
    krb5_error_code ret;
    struct ntlm_buf buf;
    krb5_data data;
    ntlm_cred dn;
    kcmuuid_t uuid;
    ssize_t sret;

    if (credential_data == NULL)
	return GSS_S_FAILURE;

    if (!gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD))
	return GSS_S_FAILURE;

    if (name == NULL)
	return GSS_S_FAILURE;
	
    ret = krb5_init_context(&context);
    if (ret)
	return GSS_S_FAILURE;

    {
	gss_buffer_t buffer;
	char *password;
	
	buffer = (gss_buffer_t)credential_data;
	password = malloc(buffer->length + 1);
	if (password == NULL) {
	    ret = ENOMEM;
	    goto out;
	}
	memcpy(password, buffer->value, buffer->length);
	password[buffer->length] = '\0';
	
	heim_ntlm_nt_key(password, &buf);
	memset(password, 0, strlen(password));
	free(password);
    }

    data.data = buf.data;
    data.length = buf.length;
	
    krb5_kcm_storage_request(context, KCM_OP_ADD_NTLM_CRED, &request);
	
    krb5_store_stringz(request, name->user);
    krb5_store_stringz(request, name->domain);
    krb5_store_data(request, data);
    
    ret = krb5_kcm_call(context, request, &response, &response_data);
    krb5_storage_free(request);
    if (ret)
	goto out;
    
    sret = krb5_storage_read(response, &uuid, sizeof(uuid));

    krb5_storage_free(response);
    krb5_data_free(&response_data);

    if (sret != sizeof(uuid)) {
	ret = KRB5_CC_IO;
	goto out;
    }

    heim_ntlm_free_buf(&buf);

    dn = calloc(1, sizeof(*dn));
    if (dn == NULL) {
	major = GSS_S_FAILURE;
	goto out;
    }

    dn->user = strdup(name->user);
    dn->domain = strdup(name->domain);
    dn->flags = NTLM_UUID;
    memcpy(dn->uuid, uuid, sizeof(dn->uuid));

    *output_cred_handle = (gss_cred_id_t)dn;
    
    major = GSS_S_COMPLETE;
 out:

    krb5_free_context(context);
    if (ret)
	major = GSS_S_FAILURE;

    return major;
}
OM_uint32
_gss_ntlm_have_cred(OM_uint32 *minor,
		    const ntlm_name target_name,
		    ntlm_cred *rcred)
{
    krb5_context context;
    krb5_error_code ret;
    krb5_storage *request, *response;
    krb5_data response_data;
    OM_uint32 major;
    ntlm_name cred;
    kcmuuid_t uuid;
    ssize_t sret;

    ret = krb5_init_context(&context);
    if (ret) {
	*minor = ret;
	return GSS_S_FAILURE;
    }

    ret = krb5_kcm_storage_request(context, KCM_OP_HAVE_NTLM_CRED, &request);
    if (ret)
	goto out;

    ret = krb5_store_stringz(request, target_name->user);
    if (ret)
	goto out;

    ret = krb5_store_stringz(request, target_name->domain);
    if (ret)
	goto out;

    ret = krb5_kcm_call(context, request, &response, &response_data);
    krb5_storage_free(request);
    if (ret)
	goto out;

    sret = krb5_storage_read(response, uuid, sizeof(uuid));

    krb5_storage_free(response);
    krb5_data_free(&response_data);

    if (sret != sizeof(uuid)) {
	krb5_clear_error_message(context);
	return KRB5_CC_IO;
    }

    major = _gss_ntlm_duplicate_name(minor, (gss_name_t)target_name,
				     (gss_name_t *)&cred);
    if (major)
	return major;

    cred->flags |= NTLM_UUID;
    memcpy(cred->uuid, uuid, sizeof(cred->uuid));

    *rcred = (ntlm_cred)cred;
 out:
    krb5_free_context(context);
    if (ret) {
	*minor = ret;
	major = GSS_S_FAILURE;
    }

    return major;
}
static krb5_error_code
kcm_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
{
    krb5_error_code ret;
    krb5_kcm_cursor c;
    krb5_storage *request, *response;
    krb5_data response_data;

    *cursor = NULL;

    c = calloc(1, sizeof(*c));
    if (c == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret,
			       N_("malloc: out of memory", ""));
	goto out;
    }

    ret = krb5_kcm_storage_request(context, KCM_OP_GET_CACHE_UUID_LIST, &request);
    if (ret)
	goto out;

    ret = krb5_kcm_call(context, request, &response, &response_data);
    krb5_storage_free(request);
    if (ret)
	goto out;

    while (1) {
	ssize_t sret;
	kcmuuid_t uuid;
	void *ptr;

	sret = krb5_storage_read(response, &uuid, sizeof(uuid));
	if (sret == 0) {
	    ret = 0;
	    break;
	} else if (sret != sizeof(uuid)) {
	    ret = EINVAL;
	    goto out;
	}

	ptr = realloc(c->uuids, sizeof(c->uuids[0]) * (c->length + 1));
	if (ptr == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret,
				   N_("malloc: out of memory", ""));
	    goto out;
	}
	c->uuids = ptr;

	memcpy(&c->uuids[c->length], &uuid, sizeof(uuid));
	c->length += 1;
    }

    krb5_storage_free(response);
    krb5_data_free(&response_data);

 out:
    if (ret && c) {
        free(c->uuids);
        free(c);
    } else
	*cursor = c;

    return ret;
}
Exemple #30
0
void GSSAPI_CALLCONV
_gss_ntlm_iter_creds_f(OM_uint32 flags,
		       void *userctx ,
		       void (*cred_iter)(void *, gss_OID, gss_cred_id_t))
{
#ifdef HAVE_KCM
    krb5_error_code ret;
    krb5_context context = NULL;
    krb5_storage *request, *response;
    krb5_data response_data;

    ret = krb5_init_context(&context);
    if (ret)
	goto done;

    ret = krb5_kcm_storage_request(context, KCM_OP_GET_NTLM_USER_LIST, &request);
    if (ret)
	goto done;

    ret = krb5_kcm_call(context, request, &response, &response_data);
    krb5_storage_free(request);
    if (ret)
	goto done;

    while (1) {
	uint32_t morep;
	char *user = NULL, *domain = NULL;
	ntlm_cred dn;

	ret = krb5_ret_uint32(response, &morep);
	if (ret) goto out;

	if (!morep) goto out;

	ret = krb5_ret_stringz(response, &user);
	if (ret) goto out;
	ret = krb5_ret_stringz(response, &domain);
	if (ret) {
	    free(user);
	    goto out;
	}

	dn = calloc(1, sizeof(*dn));
	if (dn == NULL) {
	    free(user);
	    free(domain);
	    goto out;
	}
	dn->username = user;
	dn->domain = domain;

	cred_iter(userctx, GSS_NTLM_MECHANISM, (gss_cred_id_t)dn);
    }
 out:
    krb5_storage_free(response);
    krb5_data_free(&response_data);
 done:
    if (context)
	krb5_free_context(context);
#endif /* HAVE_KCM */
    (*cred_iter)(userctx, NULL, NULL);
}