1226031Sstas/*
2226031Sstas * Copyright (c) 2011, PADL Software Pty Ltd.
3226031Sstas * All rights reserved.
4226031Sstas *
5226031Sstas * Redistribution and use in source and binary forms, with or without
6226031Sstas * modification, are permitted provided that the following conditions
7226031Sstas * are met:
8226031Sstas *
9226031Sstas * 1. Redistributions of source code must retain the above copyright
10226031Sstas *    notice, this list of conditions and the following disclaimer.
11226031Sstas *
12226031Sstas * 2. Redistributions in binary form must reproduce the above copyright
13226031Sstas *    notice, this list of conditions and the following disclaimer in the
14226031Sstas *    documentation and/or other materials provided with the distribution.
15226031Sstas *
16226031Sstas * 3. Neither the name of PADL Software nor the names of its contributors
17226031Sstas *    may be used to endorse or promote products derived from this software
18226031Sstas *    without specific prior written permission.
19226031Sstas *
20226031Sstas * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23226031Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30226031Sstas * SUCH DAMAGE.
31226031Sstas */
32226031Sstas
33226031Sstas#include "mech_locl.h"
34226031Sstas
35226031SstasGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
36226031Sstasgss_acquire_cred_with_password(OM_uint32 *minor_status,
37226031Sstas			       const gss_name_t desired_name,
38226031Sstas			       const gss_buffer_t password,
39226031Sstas			       OM_uint32 time_req,
40226031Sstas			       const gss_OID_set desired_mechs,
41226031Sstas			       gss_cred_usage_t cred_usage,
42226031Sstas			       gss_cred_id_t *output_cred_handle,
43226031Sstas			       gss_OID_set *actual_mechs,
44226031Sstas			       OM_uint32 *time_rec)
45226031Sstas{
46226031Sstas    OM_uint32 major_status, tmp_minor;
47226031Sstas
48226031Sstas    if (desired_mechs == GSS_C_NO_OID_SET) {
49226031Sstas	major_status = _gss_acquire_cred_ext(minor_status,
50226031Sstas					     desired_name,
51226031Sstas					     GSS_C_CRED_PASSWORD,
52226031Sstas					     password,
53226031Sstas					     time_req,
54226031Sstas					     GSS_C_NO_OID,
55226031Sstas					     cred_usage,
56226031Sstas					     output_cred_handle);
57226031Sstas	if (GSS_ERROR(major_status))
58226031Sstas	    return major_status;
59226031Sstas    } else {
60226031Sstas	size_t i;
61226031Sstas	struct _gss_cred *new_cred;
62226031Sstas
63226031Sstas	new_cred = calloc(1, sizeof(*new_cred));
64226031Sstas	if (new_cred == NULL) {
65226031Sstas	    *minor_status = ENOMEM;
66226031Sstas	    return GSS_S_FAILURE;
67226031Sstas	}
68226031Sstas	HEIM_SLIST_INIT(&new_cred->gc_mc);
69226031Sstas
70226031Sstas	for (i = 0; i < desired_mechs->count; i++) {
71226031Sstas	    struct _gss_cred *tmp_cred = NULL;
72226031Sstas	    struct _gss_mechanism_cred *mc;
73226031Sstas
74226031Sstas	    major_status = _gss_acquire_cred_ext(minor_status,
75226031Sstas						 desired_name,
76226031Sstas						 GSS_C_CRED_PASSWORD,
77226031Sstas						 password,
78226031Sstas						 time_req,
79226031Sstas						 &desired_mechs->elements[i],
80226031Sstas						 cred_usage,
81226031Sstas						 (gss_cred_id_t *)&tmp_cred);
82226031Sstas	    if (GSS_ERROR(major_status))
83226031Sstas		continue;
84226031Sstas
85226031Sstas	    mc = HEIM_SLIST_FIRST(&tmp_cred->gc_mc);
86226031Sstas	    if (mc) {
87226031Sstas		HEIM_SLIST_REMOVE_HEAD(&tmp_cred->gc_mc, gmc_link);
88226031Sstas		HEIM_SLIST_INSERT_HEAD(&new_cred->gc_mc, mc, gmc_link);
89226031Sstas	    }
90226031Sstas
91226031Sstas	    gss_release_cred(&tmp_minor, (gss_cred_id_t *)&tmp_cred);
92226031Sstas	}
93226031Sstas
94226031Sstas	if (!HEIM_SLIST_FIRST(&new_cred->gc_mc)) {
95226031Sstas	    free(new_cred);
96226031Sstas	    *minor_status = 0;
97226031Sstas	    return GSS_S_NO_CRED;
98226031Sstas	}
99226031Sstas
100226031Sstas	*output_cred_handle = (gss_cred_id_t)new_cred;
101226031Sstas    }
102226031Sstas
103226031Sstas    if (actual_mechs != NULL || time_rec != NULL) {
104226031Sstas	major_status = gss_inquire_cred(minor_status,
105226031Sstas					*output_cred_handle,
106226031Sstas					NULL,
107226031Sstas					time_rec,
108226031Sstas					NULL,
109226031Sstas					actual_mechs);
110226031Sstas	if (GSS_ERROR(major_status)) {
111226031Sstas	    gss_release_cred(&tmp_minor, output_cred_handle);
112226031Sstas	    return major_status;
113226031Sstas	}
114226031Sstas    }
115226031Sstas
116226031Sstas    *minor_status = 0;
117226031Sstas    return GSS_S_COMPLETE;
118226031Sstas}
119