2 * Copyright (C) 2002-2004 Novell, Inc.
4 * edir_ldapext.c LDAP extension for reading eDirectory universal password
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.
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
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, contact Novell, Inc.
18 * To contact Novell about this file by physical or electronic mail, you may
19 * find current contact information at www.novell.com.
24 /* NMAS error codes */
25 #define NMAS_E_BASE (-1600)
27 #define NMAS_SUCCESS 0
28 #define NMAS_E_SUCCESS NMAS_SUCCESS /* Alias */
29 #define NMAS_OK NMAS_SUCCESS /* Alias */
31 #define NMAS_E_FRAG_FAILURE (NMAS_E_BASE-31) /* -1631 0xFFFFF9A1 */
32 #define NMAS_E_BUFFER_OVERFLOW (NMAS_E_BASE-33) /* -1633 0xFFFFF99F */
33 #define NMAS_E_SYSTEM_RESOURCES (NMAS_E_BASE-34) /* -1634 0xFFFFF99E */
34 #define NMAS_E_INSUFFICIENT_MEMORY (NMAS_E_BASE-35) /* -1635 0xFFFFF99D */
35 #define NMAS_E_NOT_SUPPORTED (NMAS_E_BASE-36) /* -1636 0xFFFFF99C */
36 #define NMAS_E_INVALID_PARAMETER (NMAS_E_BASE-43) /* -1643 0xFFFFF995 */
37 #define NMAS_E_INVALID_VERSION (NMAS_E_BASE-52) /* -1652 0xFFFFF98C */
39 /* OID of LDAP extenstion calls to read Universal Password */
40 #define NMASLDAP_GET_PASSWORD_REQUEST "2.16.840.1.113719.1.39.42.100.13"
41 #define NMASLDAP_GET_PASSWORD_RESPONSE "2.16.840.1.113719.1.39.42.100.14"
43 #define NMAS_LDAP_EXT_VERSION 1
47 /* ------------------------------------------------------------------------
48 * berEncodePasswordData
49 * ==============================
50 * RequestBer contents:
51 * clientVersion INTEGER
52 * targetObjectDN OCTET STRING
53 * password1 OCTET STRING
54 * password2 OCTET STRING
57 * This function takes the request BER value and input data items
58 * and BER encodes the data into the BER value
60 * ------------------------------------------------------------------------ */
61 int berEncodePasswordData(
62 struct berval **requestBV,
68 BerElement *requestBer = NULL;
70 char * utf8ObjPtr = NULL;
72 char * utf8PwdPtr = NULL;
74 char * utf8Pwd2Ptr = NULL;
78 utf8ObjSize = strlen(objectDN)+1;
79 utf8ObjPtr = objectDN;
83 utf8PwdSize = strlen(password)+1;
84 utf8PwdPtr = password;
87 if (password2 != NULL)
89 utf8Pwd2Size = strlen(password2)+1;
90 utf8Pwd2Ptr = password2;
93 /* Allocate a BerElement for the request parameters.*/
94 if((requestBer = ber_alloc()) == NULL)
96 err = NMAS_E_FRAG_FAILURE;
100 if (password != NULL && password2 != NULL)
102 /* BER encode the NMAS Version, the objectDN, and the password */
103 rc = ber_printf(requestBer, "{iooo}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize, utf8PwdPtr, utf8PwdSize, utf8Pwd2Ptr, utf8Pwd2Size);
105 else if (password != NULL)
107 /* BER encode the NMAS Version, the objectDN, and the password */
108 rc = ber_printf(requestBer, "{ioo}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize, utf8PwdPtr, utf8PwdSize);
112 /* BER encode the NMAS Version and the objectDN */
113 rc = ber_printf(requestBer, "{io}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize);
118 err = NMAS_E_FRAG_FAILURE;
127 * Convert the BER we just built to a berval that we'll send with the extended request.
129 if(ber_flatten(requestBer, requestBV) == LBER_ERROR)
131 err = NMAS_E_FRAG_FAILURE;
139 ber_free(requestBer, 1);
143 } /* End of berEncodePasswordData */
145 /* ------------------------------------------------------------------------
146 * berDecodeLoginData()
147 * ==============================
148 * ResponseBer contents:
149 * serverVersion INTEGER
154 * This function takes the reply BER Value and decodes the
155 * NMAS server version and return code and if a non null retData
156 * buffer was supplied, tries to decode the the return data and length
158 * ------------------------------------------------------------------------ */
159 int berDecodeLoginData(
160 struct berval *replyBV,
166 BerElement *replyBer = NULL;
167 char *retOctStr = NULL;
168 size_t retOctStrLen = 0;
170 if((replyBer = ber_init(replyBV)) == NULL)
172 err = NMAS_E_SYSTEM_RESOURCES;
178 retOctStrLen = *retDataLen + 1;
179 retOctStr = (char *)malloc(retOctStrLen);
182 err = NMAS_E_SYSTEM_RESOURCES;
186 if( (rc = ber_scanf(replyBer, "{iis}", serverVersion, &err, retOctStr, &retOctStrLen)) != -1)
188 if (*retDataLen >= retOctStrLen)
190 memcpy(retData, retOctStr, retOctStrLen);
194 err = NMAS_E_BUFFER_OVERFLOW;
197 *retDataLen = retOctStrLen;
201 err = NMAS_E_FRAG_FAILURE;
206 if( (rc = ber_scanf(replyBer, "{ii}", serverVersion, &err)) == -1)
210 err = NMAS_E_FRAG_FAILURE;
219 ber_free(replyBer, 1);
222 if (retOctStr != NULL)
224 memset(retOctStr, 0, retOctStrLen);
229 } /* End of berDecodeLoginData */
231 /* -----------------------------------------------------------------------
232 * nmasldap_get_password()
233 * ==============================
236 * This API attempts to get the universal password
238 * ------------------------------------------------------------------------ */
239 int nmasldap_get_password(
242 size_t *pwdSize, // in bytes
247 struct berval *requestBV = NULL;
248 char *replyOID = NULL;
249 struct berval *replyBV = NULL;
252 size_t pwdBufLen, bufferLen;
254 #ifdef NOT_N_PLAT_NLM
255 int currentThreadGroupID;
258 /* Validate char parameters. */
259 if(objectDN == NULL || (strlen(objectDN) == 0) || pwdSize == NULL || ld == NULL)
261 return NMAS_E_INVALID_PARAMETER;
264 bufferLen = pwdBufLen = *pwdSize;
265 pwdBuf = (char *)malloc(pwdBufLen+2);
268 return NMAS_E_INSUFFICIENT_MEMORY;
271 #ifdef NOT_N_PLAT_NLM
272 currentThreadGroupID = SetThreadGroupID(nmasLDAPThreadGroupID);
275 err = berEncodePasswordData(&requestBV, objectDN, NULL, NULL);
281 /* Call the ldap_extended_operation (synchronously) */
282 if((err = ldap_extended_operation_s(ld, NMASLDAP_GET_PASSWORD_REQUEST, requestBV, NULL, NULL, &replyOID, &replyBV)))
287 /* Make sure there is a return OID */
290 err = NMAS_E_NOT_SUPPORTED;
294 /* Is this what we were expecting to get back. */
295 if(strcmp(replyOID, NMASLDAP_GET_PASSWORD_RESPONSE))
297 err = NMAS_E_NOT_SUPPORTED;
301 /* Do we have a good returned berval? */
305 * No; returned berval means we experienced a rather drastic error.
306 * Return operations error.
308 err = NMAS_E_SYSTEM_RESOURCES;
312 err = berDecodeLoginData(replyBV, &serverVersion, &pwdBufLen, pwdBuf);
314 if(serverVersion != NMAS_LDAP_EXT_VERSION)
316 err = NMAS_E_INVALID_VERSION;
320 if (!err && pwdBufLen != 0)
322 if (*pwdSize >= pwdBufLen+1 && pwd != NULL)
324 memcpy(pwd, pwdBuf, pwdBufLen);
325 pwd[pwdBufLen] = 0; /* add null termination */
327 *pwdSize = pwdBufLen; /* does not include null termination */
337 /* Free the return OID string if one was returned. */
340 ldap_memfree(replyOID);
343 /* Free memory allocated while building the request ber and berval. */
346 ber_bvfree(requestBV);
351 memset(pwdBuf, 0, bufferLen);
355 #ifdef NOT_N_PLAT_NLM
356 SetThreadGroupID(currentThreadGroupID);
359 /* Return the appropriate error/success code. */
361 } /* end of nmasldap_get_password */