1
0

ldbm_bind.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /* bind.c - ldbm backend bind and unbind routines */
  42. #include "back-ldbm.h"
  43. #if defined( XP_WIN32 )
  44. typedef enum LDAPWAEnum {
  45. LDAPWA_NoDomainAttr = -3,
  46. LDAPWA_InvalidCredentials = -2,
  47. LDAPWA_Failure = -1,
  48. LDAPWA_Success= 0
  49. } LDAPWAStatus;
  50. int
  51. GetDomainUsername(
  52. char *pszNTuserdomainid,
  53. char *pszNTDomain,
  54. char *pszNTUsername
  55. )
  56. {
  57. char *pszAttr, *pDomain, *pUsername;
  58. if( !pszNTuserdomainid )
  59. return( 1 );
  60. // Split the specially constructed attribute.
  61. pszAttr = slapi_ch_strdup( pszNTuserdomainid );
  62. pDomain = pszAttr;
  63. pUsername = strchr( pszAttr, ':' );
  64. if( pUsername == NULL )
  65. return( 1 );
  66. // Set the end of the NT Domain name,
  67. // and the start of the NT username.
  68. *pUsername = (char)NULL;
  69. pUsername++;
  70. strcpy( pszNTDomain, pDomain);
  71. strcpy( pszNTUsername, pUsername);
  72. slapi_ch_free( (void**)&pszAttr );
  73. return( 0 );
  74. }
  75. /* Attempt Windows NT Authentication, using the password from the client app,
  76. with the NT Domain and NT username, both stored in the entry.
  77. If successful, the ldap_bind() is completed successsfully. */
  78. LDAPWAStatus
  79. WindowsAuthentication(
  80. struct backentry *e,
  81. struct berval *cred
  82. )
  83. {
  84. Slapi_Attr *a;
  85. Slapi_Value *sval = NULL;
  86. int iStatus;
  87. char szNTDomain[MAX_PATH], szNTUsername[MAX_PATH];
  88. HANDLE hToken = NULL;
  89. BOOL bLogonStatus = FALSE;
  90. int i= -1;
  91. /* Get the NT Domain and username - if the entry has such an attribute */
  92. if( !e || !e->ep_entry ||
  93. slapi_entry_attr_find( e->ep_entry, "ntuserdomainid", &a ) != 0)
  94. {
  95. return( LDAPWA_NoDomainAttr );
  96. }
  97. i= slapi_attr_first_value( a, &sval );
  98. if(sval==NULL)
  99. {
  100. return( LDAPWA_NoDomainAttr );
  101. }
  102. while(i != -1)
  103. {
  104. const struct berval *val = slapi_value_get_berval(sval);
  105. char * colon = NULL;
  106. if (!val->bv_val || (strlen(val->bv_val) > (MAX_PATH<<1))) {
  107. LDAPDebug( LDAP_DEBUG_TRACE,
  108. "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain : "
  109. "ntuserdomainid attr value too long\n",
  110. val->bv_val, 0, 0);
  111. i= slapi_attr_next_value(a, i, &sval);
  112. continue;
  113. }
  114. colon = strchr( val->bv_val, ':' );
  115. if (!colon || ((colon - val->bv_val)/sizeof(char) > MAX_PATH)) {
  116. if (!colon) {
  117. LDAPDebug( LDAP_DEBUG_TRACE,
  118. "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain : "
  119. "a colon is missing in ntuserdomainid attr value\n",
  120. val->bv_val, 0, 0);
  121. }
  122. else {
  123. LDAPDebug( LDAP_DEBUG_TRACE,
  124. "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain : "
  125. "domain in ntuserdomainid attr value too long\n",
  126. val->bv_val, 0, 0);
  127. }
  128. i= slapi_attr_next_value(a, i, &sval);
  129. continue;
  130. }
  131. if(( iStatus = GetDomainUsername( val->bv_val,
  132. szNTDomain,
  133. szNTUsername )) != 0)
  134. {
  135. i= slapi_attr_next_value(a, i, &sval);
  136. continue;
  137. }
  138. #if !defined( LOGON32_LOGON_NETWORK )
  139. /* This is specified in the WIn32 LogonUser() documentation, but not defined
  140. in the Visual C++ 4.2 include file winbase.h. A search of the lastest version
  141. of this file at www.microsoft.com finds that LOGON32_LOGON_NETWORK == 3.
  142. */
  143. #define LOGON32_LOGON_NETWORK 3
  144. #endif
  145. /* Now do the Logon attempt */
  146. bLogonStatus = LogonUser( szNTUsername, // string that specifies the user name
  147. szNTDomain, // string that specifies the domain or server
  148. cred->bv_val, // string that specifies the password
  149. LOGON32_LOGON_NETWORK, // the type of logon operation,
  150. LOGON32_PROVIDER_DEFAULT, // specifies the logon provider
  151. &hToken ); // pointer to variable to receive token handle
  152. if( bLogonStatus && hToken )
  153. CloseHandle( hToken );
  154. if( bLogonStatus )
  155. {
  156. // Successful validation
  157. LDAPDebug( LDAP_DEBUG_TRACE,
  158. "WindowsAuthentication => validated \"%s\" on NT Domain \"%s\"\n",
  159. szNTUsername, szNTDomain, 0 );
  160. return( LDAPWA_Success );
  161. }
  162. else
  163. {
  164. LDAPDebug( LDAP_DEBUG_TRACE,
  165. "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain \"%s\", reason %d\n",
  166. szNTUsername, szNTDomain, GetLastError() );
  167. return( LDAPWA_InvalidCredentials );
  168. }
  169. i= slapi_attr_next_value(a, i, &sval);
  170. }
  171. return( LDAPWA_Failure );
  172. }
  173. #endif
  174. int
  175. ldbm_back_bind( Slapi_PBlock *pb )
  176. {
  177. backend *be;
  178. ldbm_instance *inst;
  179. int method;
  180. struct berval *cred;
  181. struct ldbminfo *li;
  182. struct backentry *e;
  183. Slapi_Attr *attr;
  184. Slapi_Value **bvals;
  185. entry_address *addr;
  186. /* get parameters */
  187. slapi_pblock_get( pb, SLAPI_BACKEND, &be );
  188. slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
  189. slapi_pblock_get( pb, SLAPI_TARGET_ADDRESS, &addr );
  190. slapi_pblock_get( pb, SLAPI_BIND_METHOD, &method );
  191. slapi_pblock_get( pb, SLAPI_BIND_CREDENTIALS, &cred );
  192. inst = (ldbm_instance *) be->be_instance_info;
  193. /* always allow noauth simple binds (front end will send the result) */
  194. if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 ) {
  195. return( SLAPI_BIND_ANONYMOUS );
  196. }
  197. /*
  198. * find the target entry. find_entry() takes care of referrals
  199. * and sending errors if the entry does not exist.
  200. */
  201. if (( e = find_entry( pb, be, addr, NULL /* no txn */ )) == NULL ) {
  202. return( SLAPI_BIND_FAIL );
  203. }
  204. switch ( method ) {
  205. case LDAP_AUTH_SIMPLE:
  206. {
  207. Slapi_Value cv;
  208. if ( slapi_entry_attr_find( e->ep_entry, "userpassword", &attr ) != 0 ) {
  209. #if defined( XP_WIN32 )
  210. if( WindowsAuthentication( e, cred ) == LDAPWA_Success ) {
  211. break;
  212. }
  213. #endif
  214. slapi_send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL,
  215. NULL, 0, NULL );
  216. cache_return( &inst->inst_cache, &e );
  217. return( SLAPI_BIND_FAIL );
  218. }
  219. bvals= attr_get_present_values(attr);
  220. slapi_value_init_berval(&cv,cred);
  221. if ( slapi_pw_find_sv( bvals, &cv ) != 0 ) {
  222. #if defined( XP_WIN32 )
  223. /* One last try - attempt Windows authentication,
  224. if the user has a Windows account. */
  225. if( WindowsAuthentication( e, cred ) == LDAPWA_Success ) {
  226. break;
  227. }
  228. #endif
  229. slapi_send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL,
  230. NULL, 0, NULL );
  231. cache_return( &inst->inst_cache, &e );
  232. value_done(&cv);
  233. return( SLAPI_BIND_FAIL );
  234. }
  235. value_done(&cv);
  236. }
  237. break;
  238. default:
  239. slapi_send_ldap_result( pb, LDAP_STRONG_AUTH_NOT_SUPPORTED, NULL,
  240. "auth method not supported", 0, NULL );
  241. cache_return( &inst->inst_cache, &e );
  242. return( SLAPI_BIND_FAIL );
  243. }
  244. cache_return( &inst->inst_cache, &e );
  245. /* success: front end will send result */
  246. return( SLAPI_BIND_SUCCESS );
  247. }