]> git.sur5r.net Git - openldap/blob - libraries/liblutil/sasl.c
c1636e639ea79fa4ff3d5c2fbfbbdd4be9a85bb3
[openldap] / libraries / liblutil / sasl.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #ifdef HAVE_CYRUS_SASL
10
11 #include <stdio.h>
12 #include <ac/stdlib.h>
13 #include <ac/string.h>
14 #include <ac/unistd.h>
15
16 #include <sasl.h>
17
18 #include <ldap.h>
19 #include "lutil_ldap.h"
20
21
22 typedef struct lutil_sasl_defaults_s {
23         unsigned flags;
24         char *mech;
25         char *realm;
26         char *authcid;
27         char *passwd;
28         char *authzid;
29 } lutilSASLdefaults;
30
31
32 void *
33 lutil_sasl_defaults(
34         LDAP *ld,
35         unsigned flags,
36         char *mech,
37         char *realm,
38         char *authcid,
39         char *passwd,
40         char *authzid )
41 {
42         lutilSASLdefaults *defaults;
43         
44         defaults = ber_memalloc( sizeof( lutilSASLdefaults ) );
45
46         if( defaults == NULL ) return NULL;
47
48         defaults->flags = flags;
49         defaults->mech = mech;
50         defaults->realm = realm;
51         defaults->authcid = authcid;
52         defaults->passwd = passwd;
53         defaults->authzid = authzid;
54
55         if( defaults->mech == NULL ) {
56                 ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech );
57         }
58         if( defaults->realm == NULL ) {
59                 ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm );
60         }
61         if( defaults->authcid == NULL ) {
62                 ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid );
63         }
64         if( defaults->authzid == NULL ) {
65                 ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid );
66         }
67
68         return defaults;
69 }
70
71 static int interaction(
72         sasl_interact_t *interact, lutilSASLdefaults *defaults )
73 {
74         unsigned flags = defaults ? defaults->flags : 0;
75         const char *dflt = interact->defresult;
76         char input[1024];
77
78         int noecho=0;
79         int challenge=0;
80
81         switch( interact->id ) {
82         case SASL_CB_GETREALM:
83                 if( defaults ) dflt = defaults->realm;
84                 break;
85         case SASL_CB_AUTHNAME:
86                 if( defaults ) dflt = defaults->authcid;
87                 break;
88         case SASL_CB_PASS:
89                 if( defaults ) dflt = defaults->passwd;
90                 noecho = 1;
91                 break;
92         case SASL_CB_USER:
93                 if( defaults ) dflt = defaults->authzid;
94                 break;
95         case SASL_CB_NOECHOPROMPT:
96                 noecho = 1;
97                 challenge = 1;
98                 break;
99         case SASL_CB_ECHOPROMPT:
100                 challenge = 1;
101                 break;
102         }
103
104         if( dflt && !*dflt ) dflt = NULL;
105
106         if( flags != LUTIL_SASL_INTERACTIVE && dflt ) {
107                 goto use_default;
108         }
109
110         if( flags == LUTIL_SASL_QUIET ) {
111                 /* don't prompt */
112                 return LDAP_OTHER;
113         }
114
115         if( challenge ) {
116                 if( interact->challenge ) {
117                         fprintf( stderr, "Challenge: %s\n", interact->challenge );
118                 }
119         }
120
121         if( dflt ) {
122                 fprintf( stderr, "Default: %s\n", dflt );
123         }
124
125         sprintf( input, "%s: ",
126                 interact->prompt ? interact->prompt : "Interact" );
127
128         if( noecho ) {
129                 interact->result = (char *) getpassphrase( input );
130                 interact->len = interact->result
131                         ? strlen( interact->result ) : 0;
132
133         } else {
134                 /* prompt user */
135                 fputs( input, stderr );
136
137                 /* get input */
138                 interact->result = fgets( input, sizeof(input), stdin );
139
140                 if( interact->result == NULL ) {
141                         interact->len = 0;
142                         return LDAP_UNAVAILABLE;
143                 }
144
145                 /* len of input */
146                 interact->len = strlen(input); 
147
148                 if( interact->len > 0 && input[interact->len - 1] == '\n' ) {
149                         /* input includes '\n', trim it */
150                         interact->len--;
151                         input[interact->len] = '\0';
152                 }
153         }
154
155
156         if( interact->len > 0 ) {
157                 /* duplicate */
158                 char *p = interact->result;
159                 interact->result = strdup( p );
160
161                 /* zap */
162                 memset( p, '\0', interact->len );
163
164         } else {
165 use_default:
166                 /* must be empty */
167                 interact->result = strdup( (dflt && *dflt) ? dflt : "" );
168                 interact->len = interact->result
169                         ? strlen( interact->result ) : 0;
170         }
171
172         if( defaults && defaults->passwd && interact->id == SASL_CB_PASS ) {
173                 /* zap password after first use */
174                 memset( defaults->passwd, '\0', strlen(defaults->passwd) );
175                 defaults->passwd = NULL;
176         }
177
178         return LDAP_SUCCESS;
179 }
180
181 int lutil_sasl_interact(
182         LDAP *ld,
183         void *defaults,
184         void *in )
185 {
186         sasl_interact_t *interact = in;
187
188         fputs( "SASL Interaction\n", stderr );
189
190         while( interact->id != SASL_CB_LIST_END ) {
191                 int rc = interaction( interact, defaults );
192
193                 if( rc )  return rc;
194                 interact++;
195         }
196         
197         return LDAP_SUCCESS;
198 }
199 #endif