]> git.ipfire.org Git - thirdparty/squid.git/blame - helpers/digest_auth/eDirectory/edir_ldapext.c
Windows port: workaround for fatal build error using latest MinGW
[thirdparty/squid.git] / helpers / digest_auth / eDirectory / edir_ldapext.c
CommitLineData
89f77e43 1/*
2 * Copyright (C) 2002-2004 Novell, Inc.
3 *
4 * edir_ldapext.c LDAP extension for reading eDirectory universal password
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License as published
8 * by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, contact Novell, Inc.
17 *
18 * To contact Novell about this file by physical or electronic mail, you may
19 * find current contact information at www.novell.com.
20 */
21
22#include <ldap.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <strings.h>
e9505fad 26
27#include "edir_ldapext.h"
28
89f77e43 29/* NMAS error codes */
30#define NMAS_E_BASE (-1600)
31
32#define NMAS_SUCCESS 0
33#define NMAS_E_SUCCESS NMAS_SUCCESS /* Alias */
34#define NMAS_OK NMAS_SUCCESS /* Alias */
35
36#define NMAS_E_FRAG_FAILURE (NMAS_E_BASE-31) /* -1631 0xFFFFF9A1 */
37#define NMAS_E_BUFFER_OVERFLOW (NMAS_E_BASE-33) /* -1633 0xFFFFF99F */
38#define NMAS_E_SYSTEM_RESOURCES (NMAS_E_BASE-34) /* -1634 0xFFFFF99E */
39#define NMAS_E_INSUFFICIENT_MEMORY (NMAS_E_BASE-35) /* -1635 0xFFFFF99D */
40#define NMAS_E_NOT_SUPPORTED (NMAS_E_BASE-36) /* -1636 0xFFFFF99C */
41#define NMAS_E_INVALID_PARAMETER (NMAS_E_BASE-43) /* -1643 0xFFFFF995 */
42#define NMAS_E_INVALID_VERSION (NMAS_E_BASE-52) /* -1652 0xFFFFF98C */
43
44/* OID of LDAP extenstion calls to read Universal Password */
45#define NMASLDAP_GET_PASSWORD_REQUEST "2.16.840.1.113719.1.39.42.100.13"
46#define NMASLDAP_GET_PASSWORD_RESPONSE "2.16.840.1.113719.1.39.42.100.14"
47
48#define NMAS_LDAP_EXT_VERSION 1
49
50
51
52/* ------------------------------------------------------------------------
53 * berEncodePasswordData
54 * ==============================
55 * RequestBer contents:
56 * clientVersion INTEGER
57 * targetObjectDN OCTET STRING
58 * password1 OCTET STRING
59 * password2 OCTET STRING
60 *
61 * Description:
62 * This function takes the request BER value and input data items
63 * and BER encodes the data into the BER value
64 *
65 * ------------------------------------------------------------------------ */
66int berEncodePasswordData(
67 struct berval **requestBV,
68 char *objectDN,
69 char *password,
70 char *password2)
71{
72 int err = 0, rc=0;
73 BerElement *requestBer = NULL;
74
75 char * utf8ObjPtr = NULL;
76 int utf8ObjSize = 0;
77 char * utf8PwdPtr = NULL;
78 int utf8PwdSize = 0;
79 char * utf8Pwd2Ptr = NULL;
80 int utf8Pwd2Size = 0;
81
82
83 utf8ObjSize = strlen(objectDN)+1;
84 utf8ObjPtr = objectDN;
85
86 if (password != NULL)
87 {
88 utf8PwdSize = strlen(password)+1;
89 utf8PwdPtr = password;
90 }
91
92 if (password2 != NULL)
93 {
94 utf8Pwd2Size = strlen(password2)+1;
95 utf8Pwd2Ptr = password2;
96 }
97
98 /* Allocate a BerElement for the request parameters.*/
99 if((requestBer = ber_alloc()) == NULL)
100 {
101 err = NMAS_E_FRAG_FAILURE;
102 goto Cleanup;
103 }
104
105 if (password != NULL && password2 != NULL)
106 {
107 /* BER encode the NMAS Version, the objectDN, and the password */
108 rc = ber_printf(requestBer, "{iooo}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize, utf8PwdPtr, utf8PwdSize, utf8Pwd2Ptr, utf8Pwd2Size);
109 }
110 else if (password != NULL)
111 {
112 /* BER encode the NMAS Version, the objectDN, and the password */
113 rc = ber_printf(requestBer, "{ioo}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize, utf8PwdPtr, utf8PwdSize);
114 }
115 else
116 {
117 /* BER encode the NMAS Version and the objectDN */
118 rc = ber_printf(requestBer, "{io}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize);
119 }
120
121 if (rc < 0)
122 {
123 err = NMAS_E_FRAG_FAILURE;
124 goto Cleanup;
125 }
126 else
127 {
128 err = 0;
129 }
130
131 /*
132 * Convert the BER we just built to a berval that we'll send with the extended request.
133 */
134 if(ber_flatten(requestBer, requestBV) == LBER_ERROR)
135 {
136 err = NMAS_E_FRAG_FAILURE;
137 goto Cleanup;
138 }
139
140Cleanup:
141
142 if(requestBer)
143 {
144 ber_free(requestBer, 1);
145 }
146
147 return err;
148} /* End of berEncodePasswordData */
149
150/* ------------------------------------------------------------------------
151 * berDecodeLoginData()
152 * ==============================
153 * ResponseBer contents:
154 * serverVersion INTEGER
155 * error INTEGER
156 * data OCTET STRING
157 *
158 * Description:
159 * This function takes the reply BER Value and decodes the
160 * NMAS server version and return code and if a non null retData
161 * buffer was supplied, tries to decode the the return data and length
162 *
163 * ------------------------------------------------------------------------ */
164int berDecodeLoginData(
165 struct berval *replyBV,
166 int *serverVersion,
167 size_t *retDataLen,
168 void *retData )
169{
170 int rc=0, err = 0;
171 BerElement *replyBer = NULL;
172 char *retOctStr = NULL;
173 size_t retOctStrLen = 0;
174
175 if((replyBer = ber_init(replyBV)) == NULL)
176 {
177 err = NMAS_E_SYSTEM_RESOURCES;
178 goto Cleanup;
179 }
180
181 if(retData)
182 {
183 retOctStrLen = *retDataLen + 1;
184 retOctStr = (char *)malloc(retOctStrLen);
185 if(!retOctStr)
186 {
187 err = NMAS_E_SYSTEM_RESOURCES;
188 goto Cleanup;
189 }
190
191 if( (rc = ber_scanf(replyBer, "{iis}", serverVersion, &err, retOctStr, &retOctStrLen)) != -1)
192 {
193 if (*retDataLen >= retOctStrLen)
194 {
195 memcpy(retData, retOctStr, retOctStrLen);
196 }
197 else if (!err)
198 {
199 err = NMAS_E_BUFFER_OVERFLOW;
200 }
201
202 *retDataLen = retOctStrLen;
203 }
204 else if (!err)
205 {
206 err = NMAS_E_FRAG_FAILURE;
207 }
208 }
209 else
210 {
211 if( (rc = ber_scanf(replyBer, "{ii}", serverVersion, &err)) == -1)
212 {
213 if (!err)
214 {
215 err = NMAS_E_FRAG_FAILURE;
216 }
217 }
218 }
219
220Cleanup:
221
222 if(replyBer)
223 {
224 ber_free(replyBer, 1);
225 }
226
227 if (retOctStr != NULL)
228 {
229 memset(retOctStr, 0, retOctStrLen);
230 free(retOctStr);
231 }
232
233 return err;
234} /* End of berDecodeLoginData */
235
236/* -----------------------------------------------------------------------
237 * nmasldap_get_password()
238 * ==============================
239 *
240 * Description:
241 * This API attempts to get the universal password
242 *
243 * ------------------------------------------------------------------------ */
244int nmasldap_get_password(
245 LDAP *ld,
246 char *objectDN,
247 size_t *pwdSize, // in bytes
248 char *pwd )
249{
250 int err = 0;
251
252 struct berval *requestBV = NULL;
253 char *replyOID = NULL;
254 struct berval *replyBV = NULL;
255 int serverVersion;
256 char *pwdBuf;
257 size_t pwdBufLen, bufferLen;
258
259#ifdef NOT_N_PLAT_NLM
260 int currentThreadGroupID;
261#endif
262
263 /* Validate char parameters. */
264 if(objectDN == NULL || (strlen(objectDN) == 0) || pwdSize == NULL || ld == NULL)
265 {
266 return NMAS_E_INVALID_PARAMETER;
267 }
268
269 bufferLen = pwdBufLen = *pwdSize;
270 pwdBuf = (char *)malloc(pwdBufLen+2);
271 if(pwdBuf == NULL)
272 {
273 return NMAS_E_INSUFFICIENT_MEMORY;
274 }
275
276#ifdef NOT_N_PLAT_NLM
277 currentThreadGroupID = SetThreadGroupID(nmasLDAPThreadGroupID);
278#endif
279
280 err = berEncodePasswordData(&requestBV, objectDN, NULL, NULL);
281 if(err)
282 {
283 goto Cleanup;
284 }
285
286 /* Call the ldap_extended_operation (synchronously) */
287 if((err = ldap_extended_operation_s(ld, NMASLDAP_GET_PASSWORD_REQUEST, requestBV, NULL, NULL, &replyOID, &replyBV)))
288 {
289 goto Cleanup;
290 }
291
292 /* Make sure there is a return OID */
293 if(!replyOID)
294 {
295 err = NMAS_E_NOT_SUPPORTED;
296 goto Cleanup;
297 }
298
299 /* Is this what we were expecting to get back. */
300 if(strcmp(replyOID, NMASLDAP_GET_PASSWORD_RESPONSE))
301 {
302 err = NMAS_E_NOT_SUPPORTED;
303 goto Cleanup;
304 }
305
306 /* Do we have a good returned berval? */
307 if(!replyBV)
308 {
309 /*
310 * No; returned berval means we experienced a rather drastic error.
311 * Return operations error.
312 */
313 err = NMAS_E_SYSTEM_RESOURCES;
314 goto Cleanup;
315 }
316
317 err = berDecodeLoginData(replyBV, &serverVersion, &pwdBufLen, pwdBuf);
318
319 if(serverVersion != NMAS_LDAP_EXT_VERSION)
320 {
321 err = NMAS_E_INVALID_VERSION;
322 goto Cleanup;
323 }
324
325 if (!err && pwdBufLen != 0)
326 {
327 if (*pwdSize >= pwdBufLen+1 && pwd != NULL)
328 {
329 memcpy(pwd, pwdBuf, pwdBufLen);
330 pwd[pwdBufLen] = 0; /* add null termination */
331 }
332 *pwdSize = pwdBufLen; /* does not include null termination */
333 }
334
335Cleanup:
336
337 if(replyBV)
338 {
339 ber_bvfree(replyBV);
340 }
341
342 /* Free the return OID string if one was returned. */
343 if(replyOID)
344 {
345 ldap_memfree(replyOID);
346 }
347
348 /* Free memory allocated while building the request ber and berval. */
349 if(requestBV)
350 {
351 ber_bvfree(requestBV);
352 }
353
354 if (pwdBuf != NULL)
355 {
356 memset(pwdBuf, 0, bufferLen);
357 free(pwdBuf);
358 }
359
360#ifdef NOT_N_PLAT_NLM
361 SetThreadGroupID(currentThreadGroupID);
362#endif
363
364 /* Return the appropriate error/success code. */
365 return err;
366} /* end of nmasldap_get_password */