pull up r24469, r24530, r24533, r24534, r24535, r24537 from trunk
[krb5.git] / src / lib / gssapi / krb5 / set_allowable_enctypes.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  * lib/gssapi/krb5/set_allowable_enctypes.c
4  *
5  * Copyright 2004  by the Massachusetts Institute of Technology.
6  * All Rights Reserved.
7  *
8  * Export of this software from the United States of America may
9  *   require a specific license from the United States Government.
10  *   It is the responsibility of any person or organization contemplating
11  *   export to obtain such a license before exporting.
12  *
13  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14  * distribute this software and its documentation for any purpose and
15  * without fee is hereby granted, provided that the above copyright
16  * notice appear in all copies and that both that copyright notice and
17  * this permission notice appear in supporting documentation, and that
18  * the name of M.I.T. not be used in advertising or publicity pertaining
19  * to distribution of the software without specific, written prior
20  * permission.  Furthermore if you modify this software you must label
21  * your software as modified software and not distribute it in such a
22  * fashion that it might be confused with the original M.I.T. software.
23  * M.I.T. makes no representations about the suitability of
24  * this software for any purpose.  It is provided "as is" without express
25  * or implied warranty.
26  *
27  * krb5_gss_set_allowable_enctypes()
28  */
29
30 /*
31  * gss_krb5_set_allowable_enctypes
32  *
33  * This function may be called by a context initiator after calling
34  * gss_acquire_cred(), but before calling gss_init_sec_context(),
35  * to restrict the set of enctypes which will be negotiated during
36  * context establishment to those in the provided array.
37  *
38  * 'cred_handle' must be a valid credential handle obtained via
39  * gss_acquire_cred().  It may not be GSS_C_NO_CREDENTIAL.
40  * gss_acquire_cred() may be called with GSS_C_NO_CREDENTIAL
41  * to get a handle to the default credential.
42  *
43  * The purpose of this function is to limit the keys that may
44  * be exported via gss_krb5_export_lucid_sec_context(); thus it
45  * should limit the enctypes of all keys that will be needed
46  * after the security context has been established.
47  * (i.e. context establishment may use a session key with a
48  * stronger enctype than in the provided array, however a
49  * subkey must be established within the enctype limits
50  * established by this function.)
51  *
52  */
53
54 #include "gssapiP_krb5.h"
55 #ifdef HAVE_STRING_H
56 #include <string.h>
57 #else
58 #include <strings.h>
59 #endif
60 #include "gssapi_krb5.h"
61
62 OM_uint32
63 gss_krb5int_set_allowable_enctypes(OM_uint32 *minor_status,
64                                    gss_cred_id_t *cred_handle,
65                                    const gss_OID desired_oid,
66                                    const gss_buffer_t value)
67 {
68     unsigned int i;
69     krb5_enctype * new_ktypes;
70     OM_uint32 major_status;
71     krb5_gss_cred_id_t cred;
72     krb5_error_code kerr = 0;
73     OM_uint32 temp_status;
74     struct krb5_gss_set_allowable_enctypes_req *req;
75
76     /* Assume a failure */
77     *minor_status = 0;
78     major_status = GSS_S_FAILURE;
79
80     assert(value->length == sizeof(*req));
81     req = (struct krb5_gss_set_allowable_enctypes_req *)value->value;
82
83     /* verify and valildate cred handle */
84     cred = (krb5_gss_cred_id_t) *cred_handle;
85
86     if (req->ktypes) {
87         for (i = 0; i < req->num_ktypes && req->ktypes[i]; i++) {
88             if (!krb5_c_valid_enctype(req->ktypes[i])) {
89                 kerr = KRB5_PROG_ETYPE_NOSUPP;
90                 goto error_out;
91             }
92         }
93     } else {
94         kerr = k5_mutex_lock(&cred->lock);
95         if (kerr)
96             goto error_out;
97         if (cred->req_enctypes)
98             free(cred->req_enctypes);
99         cred->req_enctypes = NULL;
100         k5_mutex_unlock(&cred->lock);
101         return GSS_S_COMPLETE;
102     }
103
104     /* Copy the requested ktypes into the cred structure */
105     if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * (i + 1)))) {
106         memcpy(new_ktypes, req->ktypes, sizeof(krb5_enctype) * i);
107         new_ktypes[i] = 0;      /* "null-terminate" the list */
108     }
109     else {
110         kerr = ENOMEM;
111         goto error_out;
112     }
113     kerr = k5_mutex_lock(&cred->lock);
114     if (kerr) {
115         free(new_ktypes);
116         goto error_out;
117     }
118     if (cred->req_enctypes)
119         free(cred->req_enctypes);
120     cred->req_enctypes = new_ktypes;
121     k5_mutex_unlock(&cred->lock);
122
123     /* Success! */
124     return GSS_S_COMPLETE;
125
126 error_out:
127     *minor_status = kerr;
128     return(major_status);
129 }