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