]> git.sur5r.net Git - openldap/blob - libraries/libldap/kbind.c
316b9080207958927ec0ee8c24b2b362d2bf4023
[openldap] / libraries / libldap / kbind.c
1 /*
2  *  Copyright (c) 1993 Regents of the University of Michigan.
3  *  All rights reserved.
4  *
5  *  kbind.c
6  */
7
8 #include "portable.h"
9
10 #ifndef lint 
11 static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
12 #endif
13
14 #ifdef HAVE_KERBEROS
15
16 #include <stdio.h>
17 #include <stdlib.h>
18
19 #include <ac/krb.h>
20 #include <ac/socket.h>
21 #include <ac/string.h>
22 #include <ac/time.h>
23
24 #include "ldap-int.h"
25
26
27 /*
28  * ldap_kerberos_bind1 - initiate a bind to the ldap server using
29  * kerberos authentication.  The dn is supplied.  It is assumed the user
30  * already has a valid ticket granting ticket.  The msgid of the
31  * request is returned on success (suitable for passing to ldap_result()),
32  * -1 is returned if there's trouble.
33  *
34  * Example:
35  *      ldap_kerberos_bind1( ld, "cn=manager, o=university of michigan, c=us" )
36  */
37 int
38 ldap_kerberos_bind1( LDAP *ld, char *dn )
39 {
40         BerElement      *ber;
41         char            *cred;
42         int             rc, credlen;
43 #ifdef STR_TRANSLATION
44         int             str_translation_on;
45 #endif /* STR_TRANSLATION */
46
47         /*
48          * The bind request looks like this:
49          *      BindRequest ::= SEQUENCE {
50          *              version         INTEGER,
51          *              name            DistinguishedName,
52          *              authentication  CHOICE {
53          *                      krbv42ldap      [1] OCTET STRING
54          *                      krbv42dsa       [2] OCTET STRING
55          *              }
56          *      }
57          * all wrapped up in an LDAPMessage sequence.
58          */
59
60         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1\n", 0, 0, 0 );
61
62         if ( dn == NULL )
63                 dn = "";
64
65         if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "ldapserver",
66             &credlen )) == NULL ) {
67                 return( -1 );   /* ld_errno should already be set */
68         }
69
70         /* create a message to send */
71         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) {
72                 free( cred );
73                 return( -1 );
74         }
75
76 #ifdef STR_TRANSLATION
77         if (( str_translation_on = (( ber->ber_options &
78             LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */
79                 ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
80         }
81 #endif /* STR_TRANSLATION */
82
83         /* fill it in */
84         rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
85             ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen );
86
87 #ifdef STR_TRANSLATION
88         if ( str_translation_on ) {     /* restore translation */
89                 ber->ber_options |= LBER_TRANSLATE_STRINGS;
90         }
91 #endif /* STR_TRANSLATION */
92
93         if ( rc == -1 ) {
94                 free( cred );
95                 ber_free( ber, 1 );
96                 ld->ld_errno = LDAP_ENCODING_ERROR;
97                 return( -1 );
98         }
99
100         free( cred );
101
102 #ifndef LDAP_NOCACHE
103         if ( ld->ld_cache != NULL ) {
104                 ldap_flush_cache( ld );
105         }
106 #endif /* !LDAP_NOCACHE */
107
108         /* send the message */
109         return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
110 }
111
112 int
113 ldap_kerberos_bind1_s( LDAP *ld, char *dn )
114 {
115         int             msgid;
116         LDAPMessage     *res;
117
118         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1_s\n", 0, 0, 0 );
119
120         /* initiate the bind */
121         if ( (msgid = ldap_kerberos_bind1( ld, dn )) == -1 )
122                 return( ld->ld_errno );
123
124         /* wait for a result */
125         if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
126             == -1 ) {
127                 return( ld->ld_errno ); /* ldap_result sets ld_errno */
128         }
129
130         return( ldap_result2error( ld, res, 1 ) );
131 }
132
133 /*
134  * ldap_kerberos_bind2 - initiate a bind to the X.500 server using
135  * kerberos authentication.  The dn is supplied.  It is assumed the user
136  * already has a valid ticket granting ticket.  The msgid of the
137  * request is returned on success (suitable for passing to ldap_result()),
138  * -1 is returned if there's trouble.
139  *
140  * Example:
141  *      ldap_kerberos_bind2( ld, "cn=manager, o=university of michigan, c=us" )
142  */
143 int
144 ldap_kerberos_bind2( LDAP *ld, char *dn )
145 {
146         BerElement      *ber;
147         char            *cred;
148         int             rc, credlen;
149 #ifdef STR_TRANSLATION
150         int             str_translation_on;
151 #endif /* STR_TRANSLATION */
152
153         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2\n", 0, 0, 0 );
154
155         if ( dn == NULL )
156                 dn = "";
157
158         if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "x500dsa", &credlen ))
159             == NULL ) {
160                 return( -1 );   /* ld_errno should already be set */
161         }
162
163         /* create a message to send */
164         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) {
165                 free( cred );
166                 return( -1 );
167         }
168
169 #ifdef STR_TRANSLATION
170         if (( str_translation_on = (( ber->ber_options &
171             LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */
172                 ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
173         }
174 #endif /* STR_TRANSLATION */
175
176         /* fill it in */
177         rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
178             ld->ld_version, dn, LDAP_AUTH_KRBV42, cred, credlen );
179
180
181 #ifdef STR_TRANSLATION
182         if ( str_translation_on ) {     /* restore translation */
183                 ber->ber_options |= LBER_TRANSLATE_STRINGS;
184         }
185 #endif /* STR_TRANSLATION */
186
187         free( cred );
188
189         if ( rc == -1 ) {
190                 ber_free( ber, 1 );
191                 ld->ld_errno = LDAP_ENCODING_ERROR;
192                 return( -1 );
193         }
194
195         /* send the message */
196         return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
197 }
198
199 /* synchronous bind to DSA using kerberos */
200 int
201 ldap_kerberos_bind2_s( LDAP *ld, char *dn )
202 {
203         int             msgid;
204         LDAPMessage     *res;
205
206         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2_s\n", 0, 0, 0 );
207
208         /* initiate the bind */
209         if ( (msgid = ldap_kerberos_bind2( ld, dn )) == -1 )
210                 return( ld->ld_errno );
211
212         /* wait for a result */
213         if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
214             == -1 ) {
215                 return( ld->ld_errno ); /* ldap_result sets ld_errno */
216         }
217
218         return( ldap_result2error( ld, res, 1 ) );
219 }
220
221 /* synchronous bind to ldap and DSA using kerberos */
222 int
223 ldap_kerberos_bind_s( LDAP *ld, char *dn )
224 {
225         int     err;
226
227         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind_s\n", 0, 0, 0 );
228
229         if ( (err = ldap_kerberos_bind1_s( ld, dn )) != LDAP_SUCCESS )
230                 return( err );
231
232         return( ldap_kerberos_bind2_s( ld, dn ) );
233 }
234
235
236 #ifndef AUTHMAN
237 /*
238  * ldap_get_kerberosv4_credentials - obtain kerberos v4 credentials for ldap.
239  * The dn of the entry to which to bind is supplied.  It's assumed the
240  * user already has a tgt.
241  */
242
243 char *
244 ldap_get_kerberosv4_credentials( LDAP *ld, char *who, char *service, int *len )
245 {
246         KTEXT_ST        ktxt;
247         int             err;
248         char            realm[REALM_SZ], *cred, *krbinstance;
249
250         Debug( LDAP_DEBUG_TRACE, "ldap_get_kerberosv4_credentials\n", 0, 0, 0 );
251
252         if ( (err = krb_get_tf_realm( tkt_string(), realm )) != KSUCCESS ) {
253 #ifdef LDAP_LIBUI
254                 fprintf( stderr, "krb_get_tf_realm failed (%s)\n",
255                     krb_err_txt[err] );
256 #endif /* LDAP_LIBUI */
257                 ld->ld_errno = LDAP_INVALID_CREDENTIALS;
258                 return( NULL );
259         }
260
261 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
262         krbinstance = ld->ld_defconn->lconn_krbinstance;
263 #else /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
264         krbinstance = ld->ld_host;
265 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
266
267         if ( (err = krb_mk_req( &ktxt, service, krbinstance, realm, 0 ))
268             != KSUCCESS ) {
269 #ifdef LDAP_LIBUI
270                 fprintf( stderr, "krb_mk_req failed (%s)\n", krb_err_txt[err] );
271 #endif /* LDAP_LIBUI */
272                 ld->ld_errno = LDAP_INVALID_CREDENTIALS;
273                 return( NULL );
274         }
275
276         if ( ( cred = malloc( ktxt.length )) == NULL ) {
277                 ld->ld_errno = LDAP_NO_MEMORY;
278                 return( NULL );
279         }
280
281         *len = ktxt.length;
282         memcpy( cred, ktxt.dat, ktxt.length );
283
284         return( cred );
285 }
286
287 #endif /* !AUTHMAN */
288 #endif /* HAVE_KERBEROS */