Merge remote-tracking branch 'origin/rfc3961-mic'
[mech_eap.git] / mech_eap / util_moonshot.c
1 /*
2  * Copyright (c) 2011, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of JANET(UK) nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #include "gssapiP_eap.h"
34
35 #ifdef HAVE_MOONSHOT_GET_IDENTITY
36 #include <libmoonshot.h>
37
38 static OM_uint32
39 libMoonshotMapError(OM_uint32 *minor,
40                     MoonshotError **pError)
41 {
42     MoonshotError *error = *pError;
43
44     GSSEAP_ASSERT(error != NULL);
45
46     switch (error->code) {
47     case MOONSHOT_ERROR_UNABLE_TO_START_SERVICE:
48         *minor = GSSEAP_UNABLE_TO_START_IDENTITY_SERVICE;
49         break;
50     case MOONSHOT_ERROR_NO_IDENTITY_SELECTED:
51         *minor = GSSEAP_NO_IDENTITY_SELECTED;
52         break;
53     case MOONSHOT_ERROR_INSTALLATION_ERROR:
54         *minor = GSSEAP_IDENTITY_SERVICE_INSTALL_ERROR;
55         break;
56     case MOONSHOT_ERROR_OS_ERROR:
57         *minor = GSSEAP_IDENTITY_SERVICE_OS_ERROR;
58         break;
59     case MOONSHOT_ERROR_IPC_ERROR:
60         *minor = GSSEAP_IDENTITY_SERVICE_IPC_ERROR;
61         break;
62     default:
63         *minor = GSSEAP_IDENTITY_SERVICE_UNKNOWN_ERROR;
64         break;
65     }
66
67     gssEapSaveStatusInfo(*minor, error->message);
68     moonshot_error_free(error);
69     *pError = NULL;
70
71     return GSS_S_CRED_UNAVAIL;
72 }
73
74 OM_uint32
75 libMoonshotResolveDefaultIdentity(OM_uint32 *minor,
76                                   const gss_cred_id_t cred,
77                                   gss_name_t *pName)
78 {
79     OM_uint32 major, tmpMinor;
80     gss_OID nameMech = gssEapPrimaryMechForCred(cred);
81     gss_name_t name = GSS_C_NO_NAME;
82     gss_buffer_desc tmpBuffer = GSS_C_EMPTY_BUFFER;
83     char *nai = NULL;
84     char *password = NULL;
85     char *serverCertificateHash = NULL;
86     char *caCertificate = NULL;
87     char *subjectNameConstraint = NULL;
88     char *subjectAltNameConstraint = NULL;
89     MoonshotError *error = NULL;
90
91     *pName = GSS_C_NO_NAME;
92
93     if (!moonshot_get_default_identity(&nai,
94                                        &password,
95                                        &serverCertificateHash,
96                                        &caCertificate,
97                                        &subjectNameConstraint,
98                                        &subjectAltNameConstraint,
99                                        &error)) {
100         if (error->code == MOONSHOT_ERROR_NO_IDENTITY_SELECTED) {
101             major = GSS_S_CRED_UNAVAIL;
102             *minor = GSSEAP_NO_DEFAULT_IDENTITY;
103             moonshot_error_free(error);
104         } else
105             major = libMoonshotMapError(minor, &error);
106         goto cleanup;
107     }
108
109     tmpBuffer.value = nai;
110     tmpBuffer.length = strlen(nai);
111
112     major = gssEapImportName(minor, &tmpBuffer, GSS_C_NT_USER_NAME, nameMech, &name);
113     if (GSS_ERROR(major))
114         goto cleanup;
115
116     *pName = name;
117     name = GSS_C_NO_NAME;
118
119 cleanup:
120     moonshot_free(nai);
121     moonshot_free(password);
122     moonshot_free(serverCertificateHash);
123     moonshot_free(caCertificate);
124     moonshot_free(subjectNameConstraint);
125     moonshot_free(subjectAltNameConstraint);
126
127     gssEapReleaseName(&tmpMinor, &name);
128
129     return major;
130 }
131
132 static int stringEmpty(const char * s)
133 {
134     if (s == NULL)
135       return 1;
136     if (strlen(s) > 0)
137         return 0;
138     return 1;
139 }
140
141 OM_uint32
142 libMoonshotResolveInitiatorCred(OM_uint32 *minor,
143                                 gss_cred_id_t cred,
144                                 const gss_name_t targetName)
145 {
146     OM_uint32 major, tmpMinor;
147     gss_OID nameMech = gssEapPrimaryMechForCred(cred);
148     gss_buffer_desc initiator = GSS_C_EMPTY_BUFFER;
149     gss_buffer_desc target = GSS_C_EMPTY_BUFFER;
150     gss_buffer_desc tmpBuffer = GSS_C_EMPTY_BUFFER;
151     char *nai = NULL;
152     char *password = NULL;
153     char *serverCertificateHash = NULL;
154     char *caCertificate = NULL;
155     char *subjectNameConstraint = NULL;
156     char *subjectAltNameConstraint = NULL;
157     MoonshotError *error = NULL;
158
159     if (cred->name != GSS_C_NO_NAME) {
160         major = gssEapExportName(minor, cred->name, &initiator);
161         if (GSS_ERROR(major))
162             goto cleanup;
163     }
164
165     if (targetName != GSS_C_NO_NAME) {
166         major = gssEapExportName(minor, targetName, &target);
167         if (GSS_ERROR(major))
168             goto cleanup;
169     }
170
171     if (!moonshot_get_identity((const char *)initiator.value,
172                                (const char *)cred->password.value,
173                                (const char *)target.value,
174                                &nai,
175                                &password,
176                                &serverCertificateHash,
177                                &caCertificate,
178                                &subjectNameConstraint,
179                                &subjectAltNameConstraint,
180                                &error)) {
181         major = libMoonshotMapError(minor, &error);
182         goto cleanup;
183     }
184
185     gssEapReleaseName(&tmpMinor, &cred->name);
186
187     tmpBuffer.value = nai;
188     tmpBuffer.length = strlen(nai);
189
190     major = gssEapImportName(minor, &tmpBuffer, GSS_C_NT_USER_NAME,
191                              nameMech, &cred->name);
192     if (GSS_ERROR(major))
193         goto cleanup;
194
195     tmpBuffer.value = password;
196     tmpBuffer.length = strlen(password);
197
198     major = gssEapSetCredPassword(minor, cred, &tmpBuffer);
199     if (GSS_ERROR(major))
200         goto cleanup;
201
202     gss_release_buffer(&tmpMinor, &cred->caCertificate);
203     gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
204     gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
205
206     if (!stringEmpty(serverCertificateHash)) {
207         size_t len = strlen(serverCertificateHash);
208
209         #define HASH_PREFIX             "hash://server/sha256/"
210         #define HASH_PREFIX_LEN         (sizeof(HASH_PREFIX) - 1)
211
212         cred->caCertificate.value = GSSEAP_MALLOC(HASH_PREFIX_LEN + len + 1);
213         if (cred->caCertificate.value == NULL) {
214             major = GSS_S_FAILURE;
215             *minor = ENOMEM;
216             goto cleanup;
217         }
218
219         memcpy(cred->caCertificate.value, HASH_PREFIX, HASH_PREFIX_LEN);
220         memcpy((char *)cred->caCertificate.value + HASH_PREFIX_LEN, serverCertificateHash, len);
221
222         ((char *)cred->caCertificate.value)[HASH_PREFIX_LEN + len] = '\0';
223
224         cred->caCertificate.length = HASH_PREFIX_LEN + len;
225     } else if (!stringEmpty(caCertificate)) {
226         makeStringBufferOrCleanup(caCertificate, &cred->caCertificate);
227     }
228
229     if (!stringEmpty(subjectNameConstraint))
230         makeStringBufferOrCleanup(subjectNameConstraint, &cred->subjectNameConstraint);
231     if (!stringEmpty(subjectAltNameConstraint))
232         makeStringBufferOrCleanup(subjectAltNameConstraint, &cred->subjectAltNameConstraint);
233
234 cleanup:
235     moonshot_free(nai);
236     moonshot_free(password);
237     moonshot_free(serverCertificateHash);
238     moonshot_free(caCertificate);
239     moonshot_free(subjectNameConstraint);
240     moonshot_free(subjectAltNameConstraint);
241
242     gss_release_buffer(&tmpMinor, &initiator);
243     gss_release_buffer(&tmpMinor, &target);
244
245     return major;
246 }
247 #endif /* HAVE_MOONSHOT_GET_IDENTITY */