2 * Copyright (c) 1993 Regents of the University of Michigan.
9 static char copyright
[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
26 #if !defined(DOS) && !defined( _WIN32 )
27 #include <sys/types.h>
28 #endif /* !DOS && !_WIN32 */
30 #include <sys/socket.h>
40 * ldap_kerberos_bind1 - initiate a bind to the ldap server using
41 * kerberos authentication. The dn is supplied. It is assumed the user
42 * already has a valid ticket granting ticket. The msgid of the
43 * request is returned on success (suitable for passing to ldap_result()),
44 * -1 is returned if there's trouble.
47 * ldap_kerberos_bind1( ld, "cn=manager, o=university of michigan, c=us" )
50 ldap_kerberos_bind1( LDAP
*ld
, char *dn
)
55 char *get_kerberosv4_credentials();
56 #ifdef STR_TRANSLATION
57 int str_translation_on
;
58 #endif /* STR_TRANSLATION */
61 * The bind request looks like this:
62 * BindRequest ::= SEQUENCE {
64 * name DistinguishedName,
65 * authentication CHOICE {
66 * krbv42ldap [1] OCTET STRING
67 * krbv42dsa [2] OCTET STRING
70 * all wrapped up in an LDAPMessage sequence.
73 Debug( LDAP_DEBUG_TRACE
, "ldap_kerberos_bind1\n", 0, 0, 0 );
78 if ( (cred
= get_kerberosv4_credentials( ld
, dn
, "ldapserver",
79 &credlen
)) == NULL
) {
80 return( -1 ); /* ld_errno should already be set */
83 /* create a message to send */
84 if ( (ber
= alloc_ber_with_options( ld
)) == NULLBER
) {
89 #ifdef STR_TRANSLATION
90 if (( str_translation_on
= (( ber
->ber_options
&
91 LBER_TRANSLATE_STRINGS
) != 0 ))) { /* turn translation off */
92 ber
->ber_options
&= ~LBER_TRANSLATE_STRINGS
;
94 #endif /* STR_TRANSLATION */
97 rc
= ber_printf( ber
, "{it{isto}}", ++ld
->ld_msgid
, LDAP_REQ_BIND
,
98 ld
->ld_version
, dn
, LDAP_AUTH_KRBV41
, cred
, credlen
);
100 #ifdef STR_TRANSLATION
101 if ( str_translation_on
) { /* restore translation */
102 ber
->ber_options
|= LBER_TRANSLATE_STRINGS
;
104 #endif /* STR_TRANSLATION */
109 ld
->ld_errno
= LDAP_ENCODING_ERROR
;
116 if ( ld
->ld_cache
!= NULL
) {
117 ldap_flush_cache( ld
);
119 #endif /* !NO_CACHE */
121 /* send the message */
122 return ( send_initial_request( ld
, LDAP_REQ_BIND
, dn
, ber
));
126 ldap_kerberos_bind1_s( LDAP
*ld
, char *dn
)
131 Debug( LDAP_DEBUG_TRACE
, "ldap_kerberos_bind1_s\n", 0, 0, 0 );
133 /* initiate the bind */
134 if ( (msgid
= ldap_kerberos_bind1( ld
, dn
)) == -1 )
135 return( ld
->ld_errno
);
137 /* wait for a result */
138 if ( ldap_result( ld
, ld
->ld_msgid
, 1, (struct timeval
*) 0, &res
)
140 return( ld
->ld_errno
); /* ldap_result sets ld_errno */
143 return( ldap_result2error( ld
, res
, 1 ) );
147 * ldap_kerberos_bind2 - initiate a bind to the X.500 server using
148 * kerberos authentication. The dn is supplied. It is assumed the user
149 * already has a valid ticket granting ticket. The msgid of the
150 * request is returned on success (suitable for passing to ldap_result()),
151 * -1 is returned if there's trouble.
154 * ldap_kerberos_bind2( ld, "cn=manager, o=university of michigan, c=us" )
157 ldap_kerberos_bind2( LDAP
*ld
, char *dn
)
162 char *get_kerberosv4_credentials();
163 #ifdef STR_TRANSLATION
164 int str_translation_on
;
165 #endif /* STR_TRANSLATION */
167 Debug( LDAP_DEBUG_TRACE
, "ldap_kerberos_bind2\n", 0, 0, 0 );
172 if ( (cred
= get_kerberosv4_credentials( ld
, dn
, "x500dsa", &credlen
))
174 return( -1 ); /* ld_errno should already be set */
177 /* create a message to send */
178 if ( (ber
= alloc_ber_with_options( ld
)) == NULLBER
) {
183 #ifdef STR_TRANSLATION
184 if (( str_translation_on
= (( ber
->ber_options
&
185 LBER_TRANSLATE_STRINGS
) != 0 ))) { /* turn translation off */
186 ber
->ber_options
&= ~LBER_TRANSLATE_STRINGS
;
188 #endif /* STR_TRANSLATION */
191 rc
= ber_printf( ber
, "{it{isto}}", ++ld
->ld_msgid
, LDAP_REQ_BIND
,
192 ld
->ld_version
, dn
, LDAP_AUTH_KRBV42
, cred
, credlen
);
195 #ifdef STR_TRANSLATION
196 if ( str_translation_on
) { /* restore translation */
197 ber
->ber_options
|= LBER_TRANSLATE_STRINGS
;
199 #endif /* STR_TRANSLATION */
205 ld
->ld_errno
= LDAP_ENCODING_ERROR
;
209 /* send the message */
210 return ( send_initial_request( ld
, LDAP_REQ_BIND
, dn
, ber
));
213 /* synchronous bind to DSA using kerberos */
215 ldap_kerberos_bind2_s( LDAP
*ld
, char *dn
)
220 Debug( LDAP_DEBUG_TRACE
, "ldap_kerberos_bind2_s\n", 0, 0, 0 );
222 /* initiate the bind */
223 if ( (msgid
= ldap_kerberos_bind2( ld
, dn
)) == -1 )
224 return( ld
->ld_errno
);
226 /* wait for a result */
227 if ( ldap_result( ld
, ld
->ld_msgid
, 1, (struct timeval
*) 0, &res
)
229 return( ld
->ld_errno
); /* ldap_result sets ld_errno */
232 return( ldap_result2error( ld
, res
, 1 ) );
235 /* synchronous bind to ldap and DSA using kerberos */
237 ldap_kerberos_bind_s( LDAP
*ld
, char *dn
)
241 Debug( LDAP_DEBUG_TRACE
, "ldap_kerberos_bind_s\n", 0, 0, 0 );
243 if ( (err
= ldap_kerberos_bind1_s( ld
, dn
)) != LDAP_SUCCESS
)
246 return( ldap_kerberos_bind2_s( ld
, dn
) );
252 #define FreeWindowsLibrary() FreeLibrary(instKrbv4DLL);instKrbv4DLL = (HINSTANCE)NULL;
254 #define FreeWindowsLibrary() /* do nothing */
257 * get_kerberosv4_credentials - obtain kerberos v4 credentials for ldap.
258 * The dn of the entry to which to bind is supplied. It's assumed the
259 * user already has a tgt.
263 get_kerberosv4_credentials( LDAP
*ld
, char *who
, char *service
, int *len
)
267 char realm
[REALM_SZ
], *cred
, *krbinstance
;
269 typedef int (_cdecl
* pfn_krb_get_tf_realm
) (char FAR
*,char FAR
*);
270 typedef int (PASCAL
* pfn_krb_mk_req
) (KTEXT
,LPSTR
,LPSTR
,LPSTR
,long);
271 typedef char * (_cdecl
* pfn_tkt_string
) ();
273 static HINSTANCE instKrbv4DLL
= (HINSTANCE
)NULL
;
274 pfn_krb_get_tf_realm fptr_krb_get_tf_realm
= NULL
;
275 pfn_krb_mk_req fptr_krb_mk_req
= NULL
;
276 pfn_tkt_string fptr_tkt_string
= NULL
;
277 char* p_tkt_string
= NULL
;
281 Debug( LDAP_DEBUG_TRACE
, "get_kerberosv4_credentials\n", 0, 0, 0 );
285 * The goal is to gracefully survive the absence of krbv4win.dll
286 * and thus wshelper.dll. User's won't be able to use kerberos,
287 * but they shouldn't see a message box everytime libldap.dll loads.
289 if ( !instKrbv4DLL
) {
290 unsigned int prevMode
= SetErrorMode( SEM_NOOPENFILEERRORBOX
); // don't whine at user if you can't find it
291 instKrbv4DLL
= LoadLibrary("Krbv4win.DLL");
292 SetErrorMode( prevMode
);
294 if ( instKrbv4DLL
< HINSTANCE_ERROR
) { // can't find authlib
295 ld
->ld_errno
= LDAP_AUTH_UNKNOWN
;
299 fptr_krb_get_tf_realm
= (pfn_krb_get_tf_realm
)GetProcAddress( instKrbv4DLL
, "_krb_get_tf_realm" );
300 fptr_krb_mk_req
= (pfn_krb_mk_req
)GetProcAddress( instKrbv4DLL
, "krb_mk_req" );
301 fptr_tkt_string
= (pfn_tkt_string
)GetProcAddress( instKrbv4DLL
, "_tkt_string" );
303 // verify that we found all the routines we need
304 if (!(fptr_krb_mk_req
&& fptr_krb_get_tf_realm
&& fptr_tkt_string
)) {
305 FreeWindowsLibrary();
306 ld
->ld_errno
= LDAP_AUTH_UNKNOWN
;
311 p_tkt_string
= (fptr_tkt_string
)( );
312 if ( (err
= (fptr_krb_get_tf_realm
)( p_tkt_string
, realm
)) != KSUCCESS
) {
314 if ( (err
= krb_get_tf_realm( tkt_string(), realm
)) != KSUCCESS
) {
316 #ifndef NO_USERINTERFACE
317 fprintf( stderr
, "krb_get_tf_realm failed (%s)\n",
319 #endif /* NO_USERINTERFACE */
320 ld
->ld_errno
= LDAP_INVALID_CREDENTIALS
;
321 FreeWindowsLibrary();
325 #ifdef LDAP_REFERRALS
326 krbinstance
= ld
->ld_defconn
->lconn_krbinstance
;
327 #else /* LDAP_REFERRALS */
328 krbinstance
= ld
->ld_host
;
329 #endif /* LDAP_REFERRALS */
332 if ( !krbinstance
) { // if we don't know name of service host, no chance for service tickets
333 FreeWindowsLibrary();
334 ld
->ld_errno
= LDAP_LOCAL_ERROR
;
335 WSASetLastError(WSANO_ADDRESS
);
341 if ( (err
= (fptr_krb_mk_req
)( pKt
, service
, krbinstance
, realm
, 0 ))
343 if ( (err
= krb_mk_req( &ktxt
, service
, krbinstance
, realm
, 0 ))
346 #ifndef NO_USERINTERFACE
347 fprintf( stderr
, "krb_mk_req failed (%s)\n", krb_err_txt
[err
] );
348 #endif /* NO_USERINTERFACE */
349 ld
->ld_errno
= LDAP_INVALID_CREDENTIALS
;
350 FreeWindowsLibrary();
354 if ( ( cred
= malloc( ktxt
.length
)) == NULL
) {
355 ld
->ld_errno
= LDAP_NO_MEMORY
;
356 FreeWindowsLibrary();
361 memcpy( cred
, ktxt
.dat
, ktxt
.length
);
363 FreeWindowsLibrary();
367 #endif /* !AUTHMAN */
368 #endif /* KERBEROS */