Fixes for Heimdal (macOS) builds from Stefan.
[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                                 gss_const_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 = gssEapDisplayName(minor, cred->name, &initiator, NULL);
161         if (GSS_ERROR(major))
162             goto cleanup;
163     }
164
165     if (targetName != GSS_C_NO_NAME) {
166         major = gssEapDisplayName(minor, targetName, &target, NULL);
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->caCertificateBlob);
204     gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
205     gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
206
207     if (!stringEmpty(serverCertificateHash)) {
208         size_t len = strlen(serverCertificateHash);
209
210         #define HASH_PREFIX             "hash://server/sha256/"
211         #define HASH_PREFIX_LEN         (sizeof(HASH_PREFIX) - 1)
212
213         cred->caCertificate.value = GSSEAP_MALLOC(HASH_PREFIX_LEN + len + 1);
214         if (cred->caCertificate.value == NULL) {
215             major = GSS_S_FAILURE;
216             *minor = ENOMEM;
217             goto cleanup;
218         }
219
220         memcpy(cred->caCertificate.value, HASH_PREFIX, HASH_PREFIX_LEN);
221         memcpy((char *)cred->caCertificate.value + HASH_PREFIX_LEN, serverCertificateHash, len);
222
223         ((char *)cred->caCertificate.value)[HASH_PREFIX_LEN + len] = '\0';
224
225         cred->caCertificate.length = HASH_PREFIX_LEN + len;
226     } else if (!stringEmpty(caCertificate)) {
227         void *blobData;
228         ssize_t blobLength;
229         ssize_t maxLength = ((strlen(caCertificate) + 3) / 4) * 3;
230         if (maxLength < 3) {
231             major = GSS_S_FAILURE;
232             *minor = GSSEAP_BAD_CACERTIFICATE;
233             goto cleanup;
234         }
235         blobData = GSSEAP_MALLOC(maxLength);
236         if (blobData == NULL) {
237             major = GSS_S_FAILURE;
238             *minor = ENOMEM;
239             goto cleanup;
240         }
241
242         blobLength = base64Decode(caCertificate, blobData);
243
244         if (blobLength <= 0) {
245             major = GSS_S_DEFECTIVE_CREDENTIAL;
246             *minor = GSSEAP_BAD_CACERTIFICATE;
247             GSSEAP_FREE(blobData);
248             goto cleanup;
249         }
250         cred->caCertificateBlob.value = blobData;
251         cred->caCertificateBlob.length = blobLength;
252         makeStringBufferOrCleanup("blob://ca-cert", &cred->caCertificate);
253     }
254
255     if (!stringEmpty(subjectNameConstraint))
256         makeStringBufferOrCleanup(subjectNameConstraint, &cred->subjectNameConstraint);
257     if (!stringEmpty(subjectAltNameConstraint))
258         makeStringBufferOrCleanup(subjectAltNameConstraint, &cred->subjectAltNameConstraint);
259
260 cleanup:
261     moonshot_free(nai);
262     moonshot_free(password);
263     moonshot_free(serverCertificateHash);
264     moonshot_free(caCertificate);
265     moonshot_free(subjectNameConstraint);
266     moonshot_free(subjectAltNameConstraint);
267
268     gss_release_buffer(&tmpMinor, &initiator);
269     gss_release_buffer(&tmpMinor, &target);
270
271     return major;
272 }
273 #endif /* HAVE_MOONSHOT_GET_IDENTITY */