Imported Upstream version 0.66.1
[hcoop/debian/courier-authlib.git] / authsasl.c
1
2 /*
3 ** Copyright 1998 - 2013 Double Precision, Inc. See COPYING for
4 ** distribution information.
5 */
6
7 #include "courier_auth_config.h"
8 #include "courierauthsasl.h"
9 #include "authsaslclient.h"
10 #include "cramlib.h"
11 #include <stdlib.h>
12 #include <ctype.h>
13 #include <string.h>
14 #include <errno.h>
15
16 /* Use the SASL_LIST macro to build authsasl_list */
17
18 #define NO_SERVER_FUNC()
19
20 #define SERVER_FUNC(b) int b(const char *, const char *, \
21 char *(*)(const char *, void *), \
22 void *, \
23 char **, \
24 char **);
25
26 #define SASL(a,b,c) b
27 SASL_LIST
28
29 #undef SASL
30
31 #undef SERVER_FUNC
32 #define SERVER_FUNC(n) n
33
34 #undef NO_SERVER_FUNC
35 #define NO_SERVER_FUNC() 0
36
37 #define SASL(a,b,c) {a, b},
38
39 struct authsasl_info authsasl_list[] = {
40
41 SASL_LIST
42
43 { 0, 0}};
44
45 int auth_sasl(const char *method,
46 const char *initreply,
47 char *(*callback_func)(const char *, void *),
48 void *callback_arg,
49 char **authtype_ptr, /* Returned - AUTHTYPE */
50 char **authdata_ptr)
51 {
52 int i;
53 char *p, *q;
54
55 if ((p=malloc(strlen(method)+1)) == 0)
56 return (0);
57 strcpy(p, method);
58 for (q=p; *q; q++)
59 *q=toupper((int)(unsigned char)*q);
60
61 for (i=0; authsasl_list[i].sasl_method; i++)
62 {
63 if (strcmp(p, authsasl_list[i].sasl_method) == 0 &&
64 authsasl_list[i].sasl_func)
65 {
66 free(p);
67 return ( (*authsasl_list[i].sasl_func)
68 (method,
69 initreply, callback_func,
70 callback_arg,
71 authtype_ptr, authdata_ptr));
72 }
73 }
74 free(p);
75 errno=ENOENT;
76 return (AUTHSASL_ERROR);
77 }
78
79 int auth_sasl_ex(const char *method,
80 const char *initresponse,
81 const char *externalauth,
82 char *(*callback_func)(const char *, void *),
83 void *callback_arg,
84 char **authtype_ptr, /* Returned - AUTHTYPE */
85 char **authdata_ptr)
86 {
87 char *uid;
88 int n;
89
90 if (strcmp(method, "EXTERNAL"))
91 return auth_sasl(method, initresponse, callback_func,
92 callback_arg,
93 authtype_ptr,
94 authdata_ptr);
95
96 if (!externalauth || !*externalauth)
97 return AUTHSASL_ERROR;
98
99 if (initresponse && !*initresponse)
100 initresponse=NULL;
101
102 if (initresponse && strcmp(initresponse, externalauth))
103 return AUTHSASL_ERROR;
104
105 if (!initresponse)
106 {
107 uid=callback_func("", callback_arg);
108
109 if (*uid == '*')
110 {
111 free(uid);
112 return (AUTHSASL_ABORTED);
113 }
114
115 n=authsasl_frombase64(uid);
116
117 if (n < 0)
118 {
119 free(uid);
120 return AUTHSASL_ABORTED;
121 }
122 uid[n]=0;
123
124 if (uid[0])
125 {
126 free(uid);
127 return AUTHSASL_ABORTED;
128 }
129 free(uid);
130 }
131
132 if ((*authtype_ptr=strdup("EXTERNAL")) == NULL)
133 return AUTHSASL_ABORTED;
134
135 if ((*authdata_ptr=strdup(externalauth)) == NULL)
136 {
137 free(authtype_ptr);
138 return AUTHSASL_ABORTED;
139 }
140
141 return 0;
142 }
143
144 char *auth_sasl_extract_userid(const char *authtype,
145 const char *authdata)
146 {
147 struct cram_callback_info cci;
148 char *p;
149 char *t;
150 char *d;
151
152 if (strcmp(authtype, AUTHTYPE_LOGIN) == 0)
153 {
154 char *q;
155
156 p=strdup(authdata);
157
158 if (!p)
159 return NULL;
160
161 q=strchr(p, '\n');
162 if (q) *q=0;
163 return p;
164 }
165
166 if ((t=strdup(authtype)) == NULL)
167 return NULL;
168
169 if ((d=strdup(authdata)) == NULL)
170 {
171 free(t);
172 return NULL;
173 }
174
175 if (auth_get_cram_silent(t, d, &cci))
176 {
177 free(d);
178 free(t);
179 return (NULL);
180 }
181
182 p=strdup(cci.user);
183 free(d);
184 free(t);
185 return p;
186 }