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	"courierauth.h"
9 #include	"courierauthsasl.h"
10 #include	"authsaslclient.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 
auth_sasl(const char * method,const char * initreply,char * (* callback_func)(const char *,void *),void * callback_arg,char ** authtype_ptr,char ** authdata_ptr)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 
auth_sasl_ex(const char * method,const char * initresponse,const char * externalauth,char * (* callback_func)(const char *,void *),void * callback_arg,char ** authtype_ptr,char ** authdata_ptr)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)
103 	{
104 		uid=strdup(initresponse);
105 
106 		if (!uid)
107 			return AUTHSASL_ERROR;
108 
109 		n=authsasl_frombase64(uid);
110 
111 		if (n < 0)
112 		{
113 			free(uid);
114 			return AUTHSASL_ABORTED;
115 		}
116 		uid[n]=0;
117 
118 		if (strcmp(uid, externalauth))
119 		{
120 			free(uid);
121 			return AUTHSASL_ERROR;
122 		}
123 		free(uid);
124 	}
125 	else
126 	{
127 		uid=callback_func("", callback_arg);
128 
129 		if (*uid == '*')
130 		{
131 			free(uid);
132 			return (AUTHSASL_ABORTED);
133 		}
134 
135 		n=authsasl_frombase64(uid);
136 
137 		if (n < 0)
138 		{
139 			free(uid);
140 			return AUTHSASL_ABORTED;
141 		}
142 		uid[n]=0;
143 
144 		if (uid[0])
145 		{
146 			free(uid);
147 			return AUTHSASL_ABORTED;
148 		}
149 		free(uid);
150 	}
151 
152 	if ((*authtype_ptr=strdup("EXTERNAL")) == NULL)
153 		return AUTHSASL_ABORTED;
154 
155 	if ((*authdata_ptr=strdup(externalauth)) == NULL)
156 	{
157 		free(*authtype_ptr);
158 		return AUTHSASL_ABORTED;
159 	}
160 
161 	return 0;
162 }
163 
auth_sasl_extract_userid(const char * authtype,const char * authdata)164 char *auth_sasl_extract_userid(const char *authtype,
165 			       const char *authdata)
166 {
167 	struct	cram_callback_info	cci;
168 	char *p;
169 	char *t;
170 	char *d;
171 
172 	if (strcmp(authtype, AUTHTYPE_LOGIN) == 0)
173 	{
174 		char *q;
175 
176 		p=strdup(authdata);
177 
178 		if (!p)
179 			return NULL;
180 
181 		q=strchr(p, '\n');
182 		if (q) *q=0;
183 		return p;
184 	}
185 
186 	if ((t=strdup(authtype)) == NULL)
187 		return NULL;
188 
189 	if ((d=strdup(authdata)) == NULL)
190 	{
191 		free(t);
192 		return NULL;
193 	}
194 
195 	if (auth_get_cram_silent(t, d, &cci))
196 	{
197 		free(d);
198 		free(t);
199 		return (NULL);
200 	}
201 
202 	p=strdup(cci.user);
203 	free(d);
204 	free(t);
205 	return p;
206 }
207