1 /* saslint.h - internal SASL library definitions
2  * Rob Siemborski
3  * Tim Martin
4  */
5 /*
6  * Copyright (c) 1998-2016 Carnegie Mellon University.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. The name "Carnegie Mellon University" must not be used to
21  *    endorse or promote products derived from this software without
22  *    prior written permission. For permission or any other legal
23  *    details, please contact
24  *      Carnegie Mellon University
25  *      Center for Technology Transfer and Enterprise Creation
26  *      4615 Forbes Avenue
27  *      Suite 302
28  *      Pittsburgh, PA  15213
29  *      (412) 268-7393, fax: (412) 268-7395
30  *      innovation@andrew.cmu.edu
31  *
32  * 4. Redistributions of any form whatsoever must retain the following
33  *    acknowledgment:
34  *    "This product includes software developed by Computing Services
35  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
36  *
37  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
38  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
39  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
40  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
41  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
42  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
43  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44  */
45 
46 #ifndef SASLINT_H
47 #define SASLINT_H
48 
49 #include <config.h>
50 #include "sasl.h"
51 #include "saslplug.h"
52 #include "saslutil.h"
53 #include "prop.h"
54 
55 #ifndef INLINE
56 #if defined (WIN32)
57 /* Visual Studio: "inline" keyword is not available in C, only in C++ */
58 #define INLINE __inline
59 #else
60 #define INLINE  inline
61 #endif
62 #endif
63 
64 /* #define'd constants */
65 #define CANON_BUF_SIZE 1024
66 
67 /* Error Handling Foo */
68 /* Helpful Hints:
69  *  -Error strings are set as soon as possible (first function in stack trace
70  *   with a pointer to the sasl_conn_t.
71  *  -Error codes are set as late as possible (only in the sasl api functions),
72  *   though "as often as possible" also comes to mind to ensure correctness
73  *  -Errors from calls to _buf_alloc, _sasl_strdup, etc are assumed to be
74  *   memory errors.
75  *  -Only errors (error codes < SASL_OK) should be remembered
76  */
77 #define RETURN(conn, val) { if(conn && (val) < SASL_OK) \
78                                (conn)->error_code = (val); \
79                             return (val); }
80 #define MEMERROR(conn) {\
81     if(conn) sasl_seterror( (conn), 0, \
82                    "Out of Memory in " __FILE__ " near line %d", __LINE__ ); \
83     RETURN(conn, SASL_NOMEM) }
84 #define PARAMERROR(conn) {\
85     if(conn) sasl_seterror( (conn), SASL_NOLOG, \
86                   "Parameter error in " __FILE__ " near line %d", __LINE__ ); \
87     RETURN(conn, SASL_BADPARAM) }
88 #define INTERROR(conn, val) {\
89     if(conn) sasl_seterror( (conn), 0, \
90                    "Internal Error %d in " __FILE__ " near line %d", (val),\
91 		   __LINE__ ); \
92     RETURN(conn, (val)) }
93 
94 #ifndef PATH_MAX
95 # ifdef WIN32
96 #  define PATH_MAX MAX_PATH
97 # else
98 #  ifdef _POSIX_PATH_MAX
99 #   define PATH_MAX _POSIX_PATH_MAX
100 #  else
101 #   define PATH_MAX 1024         /* arbitrary; probably big enough.
102                                   * will probably only be 256+64 on
103                                   * pre-posix machines */
104 #  endif /* _POSIX_PATH_MAX */
105 # endif /* WIN32 */
106 #endif
107 
108 /* : Define directory delimiter in SASL_PATH/SASL_CONF_PATH variables */
109 #ifdef WIN32
110 #define PATHS_DELIMITER	';'
111 #else
112 #define PATHS_DELIMITER	':'
113 #endif
114 
115 /* A FQDN max len is 255 per RFC 1035,
116  * this means 253 chars max, we add one more for zero terminator */
117 #define MAXFQDNLEN 254
118 
119 /* Datatype Definitions */
120 typedef struct {
121   const sasl_callback_t *callbacks;
122   const char *appname;
123 } sasl_global_callbacks_t;
124 
125 typedef struct _sasl_external_properties
126 {
127     sasl_ssf_t ssf;
128     char *auth_id;
129 } _sasl_external_properties_t;
130 
131 typedef struct sasl_string_list
132 {
133     const char *d;
134     struct sasl_string_list *next;
135 } sasl_string_list_t;
136 
137 typedef struct buffer_info
138 {
139     char *data;
140     size_t curlen;
141     size_t reallen;
142 } buffer_info_t;
143 
144 typedef int add_plugin_t(const char *, void *);
145 
146 typedef struct add_plugin_list
147 {
148     const char *entryname;
149     add_plugin_t *add_plugin;
150 } add_plugin_list_t;
151 
152 enum Sasl_conn_type { SASL_CONN_UNKNOWN = 0,
153 		      SASL_CONN_SERVER = 1,
154                       SASL_CONN_CLIENT = 2 };
155 
156 struct sasl_conn {
157   enum Sasl_conn_type type;
158 
159   void (*destroy_conn)(sasl_conn_t *); /* destroy function */
160 
161   char *service;
162 
163   unsigned int flags;  /* flags passed to sasl_*_new */
164 
165   /* IP information.  A buffer of size 52 is adequate for this in its
166      longest format (see sasl.h) */
167   int got_ip_local, got_ip_remote;
168   char iplocalport[NI_MAXHOST + NI_MAXSERV];
169   char ipremoteport[NI_MAXHOST + NI_MAXSERV];
170 
171   void *context;
172   sasl_out_params_t oparams;
173 
174   sasl_security_properties_t props;
175   _sasl_external_properties_t external;
176 
177   sasl_secret_t *secret;
178 
179   int (*idle_hook)(sasl_conn_t *conn);
180   const sasl_callback_t *callbacks;
181   const sasl_global_callbacks_t *global_callbacks; /* global callbacks
182 						    * connection */
183   char *serverFQDN;
184 
185   /* Pointers to memory that we are responsible for */
186   buffer_info_t *encode_buf;
187 
188   int error_code;
189   char *error_buf, *errdetail_buf;
190   size_t error_buf_len, errdetail_buf_len;
191   char *mechlist_buf;
192   size_t mechlist_buf_len;
193 
194   char *decode_buf;
195 
196   char user_buf[CANON_BUF_SIZE+1], authid_buf[CANON_BUF_SIZE+1];
197 
198   /* Allocated by sasl_encodev if the output contains multiple SASL packet. */
199   buffer_info_t multipacket_encoded_data;
200 };
201 
202 /* Server Conn Type Information */
203 
204 typedef struct mechanism
205 {
206     server_sasl_mechanism_t m;
207     struct mechanism *next;
208 } mechanism_t;
209 
210 typedef struct mech_list {
211   const sasl_utils_t *utils;  /* gotten from plug_init */
212 
213   void *mutex;            /* mutex for this data */
214   mechanism_t *mech_list; /* list of loaded mechanisms */
215   int mech_length;        /* number of loaded mechanisms */
216 } mech_list_t;
217 
218 typedef struct context_list
219 {
220     mechanism_t *mech;
221     void *context;     /* if NULL, this mech is disabled for this connection
222 			* otherwise, use this context instead of a call
223 			* to mech_new */
224     struct context_list *next;
225 } context_list_t;
226 
227 typedef struct sasl_server_conn {
228     sasl_conn_t base; /* parts common to server + client */
229 
230     char *appname; /* application name buffer (for sparams) */
231     char *user_realm; /* domain the user authenticating is in */
232     int sent_last; /* Have we already done the last send? */
233     int authenticated;
234     mechanism_t *mech; /* mechanism trying to use */
235     sasl_server_params_t *sparams;
236     context_list_t *mech_contexts;
237     mechanism_t *mech_list; /* list of available mechanisms */
238     int mech_length;        /* number of available mechanisms */
239 } sasl_server_conn_t;
240 
241 /* Client Conn Type Information */
242 
243 typedef struct cmechanism
244 {
245     client_sasl_mechanism_t m;
246     struct cmechanism *next;
247 } cmechanism_t;
248 
249 typedef struct cmech_list {
250   const sasl_utils_t *utils;
251 
252   void *mutex;            /* mutex for this data */
253   cmechanism_t *mech_list; /* list of mechanisms */
254   int mech_length;       /* number of mechanisms */
255 
256 } cmech_list_t;
257 
258 typedef struct sasl_client_conn {
259   sasl_conn_t base; /* parts common to server + client */
260 
261   cmechanism_t *mech;
262   sasl_client_params_t *cparams;
263 
264   char *clientFQDN;
265 
266   cmechanism_t *mech_list; /* list of available mechanisms */
267   int mech_length;	   /* number of available mechanisms */
268 } sasl_client_conn_t;
269 
270 typedef struct sasl_allocation_utils {
271   sasl_malloc_t *malloc;
272   sasl_calloc_t *calloc;
273   sasl_realloc_t *realloc;
274   sasl_free_t *free;
275 } sasl_allocation_utils_t;
276 
277 typedef struct sasl_mutex_utils {
278   sasl_mutex_alloc_t *alloc;
279   sasl_mutex_lock_t *lock;
280   sasl_mutex_unlock_t *unlock;
281   sasl_mutex_free_t *free;
282 } sasl_mutex_utils_t;
283 
284 typedef struct sasl_log_utils_s {
285   sasl_log_t *log;
286 } sasl_log_utils_t;
287 
288 typedef int sasl_plaintext_verifier(sasl_conn_t *conn,
289 				    const char *userid,
290 				    const char *passwd,
291 				    const char *service,
292 				    const char *user_realm);
293 
294 struct sasl_verify_password_s {
295     char *name;
296     sasl_plaintext_verifier *verify;
297 };
298 
299 /*
300  * globals & constants
301  */
302 /*
303  * common.c
304  */
305 LIBSASL_API const sasl_utils_t *sasl_global_utils;
306 
307 extern int (*_sasl_client_idle_hook)(sasl_conn_t *conn);
308 extern int (*_sasl_server_idle_hook)(sasl_conn_t *conn);
309 
310 /* These return SASL_OK if we've actually finished cleanup,
311  * SASL_NOTINIT if that part of the library isn't initialized, and
312  * SASL_CONTINUE if we need to call them again */
313 extern int (*_sasl_client_cleanup_hook)(void);
314 extern int (*_sasl_server_cleanup_hook)(void);
315 
316 extern sasl_allocation_utils_t _sasl_allocation_utils;
317 extern sasl_mutex_utils_t _sasl_mutex_utils;
318 extern int _sasl_allocation_locked;
319 
320 void sasl_common_done(void);
321 
322 extern int _sasl_is_equal_mech(const char *req_mech,
323                                const char *plug_mech,
324                                size_t req_mech_len,
325                                int *plus);
326 
327 /*
328  * checkpw.c
329  */
330 extern struct sasl_verify_password_s _sasl_verify_password[];
331 
332 /*
333  * server.c
334  */
335 /* (this is a function call to ensure this is read-only to the outside) */
336 extern int _is_sasl_server_active(void);
337 
338 /*
339  * Allocation and Mutex utility macros
340  */
341 #define sasl_ALLOC(__size__) (_sasl_allocation_utils.malloc((__size__)))
342 #define sasl_CALLOC(__nelem__, __size__) \
343 	(_sasl_allocation_utils.calloc((__nelem__), (__size__)))
344 #define sasl_REALLOC(__ptr__, __size__) \
345 	(_sasl_allocation_utils.realloc((__ptr__), (__size__)))
346 #define sasl_FREE(__ptr__) (_sasl_allocation_utils.free((__ptr__)))
347 
348 #define sasl_MUTEX_ALLOC() (_sasl_mutex_utils.alloc())
349 #define sasl_MUTEX_LOCK(__mutex__) (_sasl_mutex_utils.lock((__mutex__)))
350 #define sasl_MUTEX_UNLOCK(__mutex__) (_sasl_mutex_utils.unlock((__mutex__)))
351 #define sasl_MUTEX_FREE(__mutex__) \
352 	(_sasl_mutex_utils.free((__mutex__)))
353 
354 /* function prototypes */
355 /*
356  * dlopen.c and staticopen.c
357  */
358 /*
359  * The differences here are:
360  * _sasl_load_plugins loads all plugins from all files
361  * _sasl_get_plugin loads the LIBRARY for an individual file
362  * _sasl_done_with_plugins frees the LIBRARIES loaded by the above 2
363  * _sasl_locate_entry locates an entrypoint in a given library
364  */
365 extern int _sasl_load_plugins(const add_plugin_list_t *entrypoints,
366 			       const sasl_callback_t *getpath_callback,
367 			       const sasl_callback_t *verifyfile_callback);
368 extern int _sasl_get_plugin(const char *file,
369 			    const sasl_callback_t *verifyfile_cb,
370 			    void **libraryptr);
371 extern int _sasl_locate_entry(void *library, const char *entryname,
372                               void **entry_point);
373 extern int _sasl_done_with_plugins();
374 
375 /*
376  * common.c
377  */
378 extern const sasl_callback_t *
379 _sasl_find_getpath_callback(const sasl_callback_t *callbacks);
380 
381 extern const sasl_callback_t *
382 _sasl_find_getconfpath_callback(const sasl_callback_t *callbacks);
383 
384 extern const sasl_callback_t *
385 _sasl_find_verifyfile_callback(const sasl_callback_t *callbacks);
386 
387 extern int _sasl_common_init(sasl_global_callbacks_t *global_callbacks);
388 
389 extern int _sasl_conn_init(sasl_conn_t *conn,
390 			   const char *service,
391 			   unsigned int flags,
392 			   enum Sasl_conn_type type,
393 			   int (*idle_hook)(sasl_conn_t *conn),
394 			   const char *serverFQDN,
395 			   const char *iplocalport,
396 			   const char *ipremoteport,
397 			   const sasl_callback_t *callbacks,
398 			   const sasl_global_callbacks_t *global_callbacks);
399 extern void _sasl_conn_dispose(sasl_conn_t *conn);
400 
401 extern sasl_utils_t *
402 _sasl_alloc_utils(sasl_conn_t *conn,
403 		  sasl_global_callbacks_t *global_callbacks);
404 extern int _sasl_free_utils(const sasl_utils_t ** utils);
405 
406 extern int
407 _sasl_getcallback(sasl_conn_t * conn,
408 		  unsigned long callbackid,
409 		  sasl_callback_ft * pproc,
410 		  void **pcontext);
411 
412 extern void
413 _sasl_log(sasl_conn_t *conn,
414 	  int level,
415 	  const char *fmt,
416 	  ...);
417 
418 void _sasl_get_errorbuf(sasl_conn_t *conn, char ***bufhdl, size_t **lenhdl);
419 int _sasl_add_string(char **out, size_t *alloclen,
420 		     size_t *outlen, const char *add);
421 
422 /* More Generic Utilities in common.c */
423 extern int _sasl_strdup(const char *in, char **out, size_t *outlen);
424 
425 /* Basically a conditional call to realloc(), if we need more */
426 int _buf_alloc(char **rwbuf, size_t *curlen, size_t newlen);
427 
428 /* convert an iovec to a single buffer */
429 int _iovec_to_buf(const struct iovec *vec,
430 		  unsigned numiov, buffer_info_t **output);
431 
432 /* Convert between string formats and sockaddr formats */
433 int _sasl_iptostring(const struct sockaddr *addr, socklen_t addrlen,
434 		     char *out, unsigned outlen);
435 int _sasl_ipfromstring(const char *addr, struct sockaddr *out,
436 		       socklen_t outlen);
437 
438 /*
439  * external plugin (external.c)
440  */
441 int external_client_plug_init(const sasl_utils_t *utils,
442 			      int max_version,
443 			      int *out_version,
444 			      sasl_client_plug_t **pluglist,
445 			      int *plugcount);
446 int external_server_plug_init(const sasl_utils_t *utils,
447 			      int max_version,
448 			      int *out_version,
449 			      sasl_server_plug_t **pluglist,
450 			      int *plugcount);
451 
452 /* Mech Listing Functions */
453 int _sasl_build_mechlist(void);
454 int _sasl_server_listmech(sasl_conn_t *conn,
455 			  const char *user,
456 			  const char *prefix,
457 			  const char *sep,
458 			  const char *suffix,
459 			  const char **result,
460 			  unsigned *plen,
461 			  int *pcount);
462 int _sasl_client_listmech(sasl_conn_t *conn,
463 			  const char *prefix,
464 			  const char *sep,
465 			  const char *suffix,
466 			  const char **result,
467 			  unsigned *plen,
468 			  int *pcount);
469 /* Just create a straight list of them */
470 sasl_string_list_t *_sasl_client_mechs(void);
471 sasl_string_list_t *_sasl_server_mechs(void);
472 
473 /*
474  * config file declarations (config.c)
475  */
476 extern const char *sasl_config_getstring(const char *key,const char *def);
477 
478 /* checkpw.c */
479 #ifdef DO_SASL_CHECKAPOP
480 extern int _sasl_auxprop_verify_apop(sasl_conn_t *conn,
481 				     const char *userstr,
482 				     const char *challenge,
483 				     const char *response,
484 				     const char *user_realm);
485 #endif /* DO_SASL_CHECKAPOP */
486 
487 /* Auxprop Plugin (sasldb.c) */
488 extern int sasldb_auxprop_plug_init(const sasl_utils_t *utils,
489 				    int max_version,
490 				    int *out_version,
491 				    sasl_auxprop_plug_t **plug,
492 				    const char *plugname);
493 
494 /*
495  * auxprop.c
496  */
497 extern int _sasl_auxprop_add_plugin(void *p, void *library);
498 extern void _sasl_auxprop_free(void);
499 extern int _sasl_auxprop_lookup(sasl_server_params_t *sparams,
500 				 unsigned flags,
501 				 const char *user, unsigned ulen);
502 
503 /*
504  * canonusr.c
505  */
506 void _sasl_canonuser_free();
507 extern int internal_canonuser_init(const sasl_utils_t *utils,
508 				   int max_version,
509 				   int *out_version,
510 				   sasl_canonuser_plug_t **plug,
511 				   const char *plugname);
512 extern int _sasl_canon_user(sasl_conn_t *conn,
513 			    const char *user,
514 			    unsigned ulen,
515 			    unsigned flags,
516 			    sasl_out_params_t *oparams);
517 int _sasl_canon_user_lookup (sasl_conn_t *conn,
518 			     const char *user,
519 			     unsigned ulen,
520 			     unsigned flags,
521 			     sasl_out_params_t *oparams);
522 
523 /*
524  * saslutil.c
525  */
526 int get_fqhostname(
527   char *name,
528   int namelen,
529   int abort_if_no_fqdn
530   );
531 
532 #ifndef HAVE_GETHOSTNAME
533 #ifdef sun
534 /* gotta define gethostname ourselves on suns */
535 extern int gethostname(char *, int);
536 #endif
537 #endif /* HAVE_GETHOSTNAME */
538 
539 #ifdef WIN32
540 char* _sasl_wchar_to_utf8(WCHAR *str);
541 WCHAR* _sasl_utf8_to_wchar(const char *str);
542 #endif
543 
544 #endif /* SASLINT_H */
545