]> git.sur5r.net Git - openldap/blob - libraries/liblutil/sasl.c
ffbd29846e67b03fadbcd18010c79a319b3c4d32
[openldap] / libraries / liblutil / sasl.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2007 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15
16 #include "portable.h"
17
18 #ifdef HAVE_CYRUS_SASL
19
20 #include <stdio.h>
21 #include <ac/stdlib.h>
22 #include <ac/string.h>
23 #include <ac/unistd.h>
24
25 #ifdef HAVE_SASL_SASL_H
26 #include <sasl/sasl.h>
27 #else
28 #include <sasl.h>
29 #endif
30
31 #include <ldap.h>
32 #include "ldap_pvt.h"
33 #include "lutil_ldap.h"
34
35
36 typedef struct lutil_sasl_defaults_s {
37         char *mech;
38         char *realm;
39         char *authcid;
40         char *passwd;
41         char *authzid;
42         char **resps;
43         int nresps;
44 } lutilSASLdefaults;
45
46
47 void
48 lutil_sasl_freedefs(
49         void *defaults )
50 {
51         lutilSASLdefaults *defs = defaults;
52         
53         if (defs->mech) ber_memfree(defs->mech);
54         if (defs->realm) ber_memfree(defs->realm);
55         if (defs->authcid) ber_memfree(defs->authcid);
56         if (defs->passwd) ber_memfree(defs->passwd);
57         if (defs->authzid) ber_memfree(defs->authzid);
58         if (defs->resps) ldap_charray_free(defs->resps);
59
60         ber_memfree(defs);
61 }
62
63 void *
64 lutil_sasl_defaults(
65         LDAP *ld,
66         char *mech,
67         char *realm,
68         char *authcid,
69         char *passwd,
70         char *authzid )
71 {
72         lutilSASLdefaults *defaults;
73         
74         defaults = ber_memalloc( sizeof( lutilSASLdefaults ) );
75
76         if( defaults == NULL ) return NULL;
77
78         defaults->mech = mech ? ber_strdup(mech) : NULL;
79         defaults->realm = realm ? ber_strdup(realm) : NULL;
80         defaults->authcid = authcid ? ber_strdup(authcid) : NULL;
81         defaults->passwd = passwd ? ber_strdup(passwd) : NULL;
82         defaults->authzid = authzid ? ber_strdup(authzid) : NULL;
83
84         if( defaults->mech == NULL ) {
85                 ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech );
86         }
87         if( defaults->realm == NULL ) {
88                 ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm );
89         }
90         if( defaults->authcid == NULL ) {
91                 ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid );
92         }
93         if( defaults->authzid == NULL ) {
94                 ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid );
95         }
96         defaults->resps = NULL;
97         defaults->nresps = 0;
98
99         return defaults;
100 }
101
102 static int interaction(
103         unsigned flags,
104         sasl_interact_t *interact,
105         lutilSASLdefaults *defaults )
106 {
107         const char *dflt = interact->defresult;
108         char input[1024];
109
110         int noecho=0;
111         int challenge=0;
112
113         switch( interact->id ) {
114         case SASL_CB_GETREALM:
115                 if( defaults ) dflt = defaults->realm;
116                 break;
117         case SASL_CB_AUTHNAME:
118                 if( defaults ) dflt = defaults->authcid;
119                 break;
120         case SASL_CB_PASS:
121                 if( defaults ) dflt = defaults->passwd;
122                 noecho = 1;
123                 break;
124         case SASL_CB_USER:
125                 if( defaults ) dflt = defaults->authzid;
126                 break;
127         case SASL_CB_NOECHOPROMPT:
128                 noecho = 1;
129                 challenge = 1;
130                 break;
131         case SASL_CB_ECHOPROMPT:
132                 challenge = 1;
133                 break;
134         }
135
136         if( dflt && !*dflt ) dflt = NULL;
137
138         if( flags != LDAP_SASL_INTERACTIVE &&
139                 ( dflt || interact->id == SASL_CB_USER ) )
140         {
141                 goto use_default;
142         }
143
144         if( flags == LDAP_SASL_QUIET ) {
145                 /* don't prompt */
146                 return LDAP_OTHER;
147         }
148
149         if( challenge ) {
150                 if( interact->challenge ) {
151                         fprintf( stderr, _("Challenge: %s\n"), interact->challenge );
152                 }
153         }
154
155         if( dflt ) {
156                 fprintf( stderr, _("Default: %s\n"), dflt );
157         }
158
159         snprintf( input, sizeof input, "%s: ",
160                 interact->prompt ? interact->prompt : _("Interact") );
161
162         if( noecho ) {
163                 interact->result = (char *) getpassphrase( input );
164                 interact->len = interact->result
165                         ? strlen( interact->result ) : 0;
166
167         } else {
168                 /* prompt user */
169                 fputs( input, stderr );
170
171                 /* get input */
172                 interact->result = fgets( input, sizeof(input), stdin );
173
174                 if( interact->result == NULL ) {
175                         interact->len = 0;
176                         return LDAP_UNAVAILABLE;
177                 }
178
179                 /* len of input */
180                 interact->len = strlen(input); 
181
182                 if( interact->len > 0 && input[interact->len - 1] == '\n' ) {
183                         /* input includes '\n', trim it */
184                         interact->len--;
185                         input[interact->len] = '\0';
186                 }
187         }
188
189
190         if( interact->len > 0 ) {
191                 /* duplicate */
192                 char *p = (char *)interact->result;
193                 ldap_charray_add(&defaults->resps, interact->result);
194                 interact->result = defaults->resps[defaults->nresps++];
195
196                 /* zap */
197                 memset( p, '\0', interact->len );
198
199         } else {
200 use_default:
201                 /* input must be empty */
202                 interact->result = (dflt && *dflt) ? dflt : "";
203                 interact->len = strlen( interact->result );
204         }
205
206         return LDAP_SUCCESS;
207 }
208
209 int lutil_sasl_interact(
210         LDAP *ld,
211         unsigned flags,
212         void *defaults,
213         void *in )
214 {
215         sasl_interact_t *interact = in;
216
217         if( ld == NULL ) return LDAP_PARAM_ERROR;
218
219         if( flags == LDAP_SASL_INTERACTIVE ) {
220                 fputs( _("SASL Interaction\n"), stderr );
221         }
222
223         while( interact->id != SASL_CB_LIST_END ) {
224                 int rc = interaction( flags, interact, defaults );
225
226                 if( rc )  return rc;
227                 interact++;
228         }
229         
230         return LDAP_SUCCESS;
231 }
232 #endif