1 /* cfmglue.c
2    by Rolf Braun, for CMU SASL on Mac OS X
3 
4    This file provides routines to allow CFM (os 9 linkage) Carbon applications
5    to use the native Mach-O SASL libraries on Mac OS X, using CFBundle to
6    load the backend libraries and automatically allocated assembly callbacks
7    $Id: cfmglue.c,v 1.4 2003/06/12 00:33:05 rbraun Exp $
8 */
9 /*
10  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  *
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in
21  *    the documentation and/or other materials provided with the
22  *    distribution.
23  *
24  * 3. The name "Carnegie Mellon University" must not be used to
25  *    endorse or promote products derived from this software without
26  *    prior written permission. For permission or any other legal
27  *    details, please contact
28  *      Office of Technology Transfer
29  *      Carnegie Mellon University
30  *      5000 Forbes Avenue
31  *      Pittsburgh, PA  15213-3890
32  *      (412) 268-4387, fax: (412) 268-7395
33  *      tech-transfer@andrew.cmu.edu
34  *
35  * 4. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by Computing Services
38  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
39  *
40  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
41  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
42  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
43  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
44  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
45  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
46  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
47  */
48 
49 #include <Carbon.h>
50 #include <string.h>
51 #include <stdlib.h>
52 #include "sasl.h"
53 #include "saslutil.h"
54 #include "prop.h"
55 
56 /* prototypes for internal functions (from saslint.h) */
57 int _sasl_add_string(char **out, int *alloclen, int *outlen, const char *add);
58 int _buf_alloc(char **rwbuf, unsigned *curlen, unsigned newlen);
59 void _sasl_get_errorbuf(sasl_conn_t *conn, char ***bufhdl, unsigned **lenhdl);
60 
61 void	*MachOFunctionPointerForCFMFunctionPointer( void *cfmfp );
62 sasl_callback_t *GetCFMCallbacks(const sasl_callback_t *callbacks);
63 void DisposeCFMCallbacks(sasl_callback_t *callbacks);
64 
65 int _cfmsasl_haveCustomAlloc = 0;
66 int _cfmsasl_haveCustomMutex = 0;
67 int _cfmsasl_initted = 0;
68 
69 /* DO NOT change the order of this struct! It MUST match that
70    of the iovec struct in /usr/include/sys/uio.h on Mac OS X!
71    It MUST also match that of the Mac OS 9 Carbon config.h since
72    Carbon CFM stuff links at runtime against whatever it's running on! */
73 struct iovec {
74     char *iov_base;
75     long iov_len;
76 };
77 
78 typedef struct
79 {
80 	CFURLRef		bundleURL;
81 	CFBundleRef		myBundle;
82 	sasl_callback_t *clientCallbacks;
83 	sasl_callback_t *serverCallbacks;
84 	int (*SASLClientNewPtr)(const char *service,
85 							const char *serverFQDN,
86 							const char *iplocalport,
87 							const char *ipremoteport,
88 							const sasl_callback_t *prompt_supp,
89 							unsigned flags,
90 							sasl_conn_t **pconn);
91 	int (*SASLClientStartPtr)(sasl_conn_t *conn,
92 								const char *mechlist,
93 								sasl_interact_t **prompt_need,
94 								const char **clientout,
95 								unsigned *clientoutlen,
96 								const char **mech);
97 	int (*SASLClientStepPtr)(sasl_conn_t *conn,
98 								const char *serverin,
99 								unsigned serverinlen,
100 								sasl_interact_t **prompt_need,
101 								const char **clientout,
102 								unsigned *clientoutlen);
103 	const char * (*SASLErrStringPtr)(int saslerr,
104 							const char *langlist,
105 							const char **outlang);
106 	const char *(*sasl_errdetailPtr)(sasl_conn_t *conn);
107 	int (*SASLGetPropPtr)(sasl_conn_t *conn, int propnum, const void **pvalue);
108 	int (*SASLSetPropPtr)(sasl_conn_t *conn,
109 							int propnum,
110 							const void *value);
111 	int (*SASLIdlePtr)(sasl_conn_t *conn);
112 	int (*SASLEncodePtr)(sasl_conn_t *conn,
113 							const char *input, unsigned inputlen,
114 							const char **output, unsigned *outputlen);
115 	int (*SASLDecodePtr)(sasl_conn_t *conn,
116 							const char *input, unsigned inputlen,
117 							const char **output, unsigned *outputlen);
118 	int (*SASLEncodeVPtr)(sasl_conn_t *conn,
119 			     const struct iovec *invec, unsigned numiov,
120 			     const char **output, unsigned *outputlen);
121 	int (*SASLDisposePtr)(sasl_conn_t **pconn);
122 	int (*SASLDonePtr)();
123 	void (*SASLSetAllocPtr)(sasl_malloc_t *, sasl_calloc_t *, sasl_realloc_t *, sasl_free_t *);
124 	int (*sasl_decode64Ptr)(const char *in, unsigned inlen,
125 			      char *out, unsigned outmax, unsigned *outlen);
126 	int (*sasl_encode64Ptr)(const char *in, unsigned inlen,
127 			      char *out, unsigned outmax, unsigned *outlen);
128 	int (*sasl_mkchalPtr)(sasl_conn_t *conn, char *buf,
129 			    unsigned maxlen, unsigned hostflag);
130 	int (*sasl_utf8verifyPtr)(const char *str, unsigned len);
131 	void (*sasl_churnPtr)(sasl_rand_t *rpool,
132 			    const char *data,
133 			    unsigned len);
134 	void (*sasl_randPtr)(sasl_rand_t *rpool,
135 			   char *buf,
136 			   unsigned len);
137 	void (*sasl_randseedPtr)(sasl_rand_t *rpool,
138 			       const char *seed,
139 			       unsigned len);
140 	void (*sasl_randfreePtr)(sasl_rand_t **rpool);
141 	int (*sasl_randcreatePtr)(sasl_rand_t **rpool);
142 	void (*SASLSetMutexPtr)(sasl_mutex_alloc_t *mn, sasl_mutex_lock_t *ml,
143                                 sasl_mutex_unlock_t *mu, sasl_mutex_free_t *md);
144 	int (*SASLServerNewPtr)(const char *service,
145 						const char *serverFQDN,
146 						const char *user_realm,
147 						const char *iplocalport,
148 						const char *ipremoteport,
149 						const sasl_callback_t *callbacks,
150 						unsigned flags,
151 						sasl_conn_t **pconn);
152 	int (*sasl_listmechPtr)(sasl_conn_t *conn,
153 			      const char *user,
154 			      const char *prefix,
155 			      const char *sep,
156 			      const char *suffix,
157 			      const char **result,
158 			      unsigned *plen,
159 			      int *pcount);
160 	int (*SASLServerStartPtr)(sasl_conn_t *conn,
161 				  const char *mech,
162 				  const char *clientin,
163 				  unsigned clientinlen,
164 				  const char **serverout,
165 				  unsigned *serveroutlen);
166 	int (*SASLServerStepPtr)(sasl_conn_t *conn,
167 		     const char *clientin,
168 		     unsigned clientinlen,
169 		     const char **serverout,
170 		     unsigned *serveroutlen);
171 	int (*sasl_checkpassPtr)(sasl_conn_t *conn,
172 			       const char *user,
173 			       unsigned userlen,
174 			       const char *pass,
175 			       unsigned passlen);
176 	int (*sasl_user_existsPtr)(sasl_conn_t *conn,
177 			 const char *service,
178 		     const char *user_realm,
179 		     const char *user);
180 	int (*sasl_setpassPtr)(sasl_conn_t *conn,
181 		 const char *user,
182 		 const char *pass,
183 		 unsigned passlen,
184 		 const char *oldpass, unsigned oldpasslen,
185 		 unsigned flags);
186 	int (*sasl_checkapopPtr)(sasl_conn_t *conn,
187 			       const char *challenge, unsigned challen,
188 			       const char *response, unsigned resplen);
189 	int (*sasl_auxprop_requestPtr)(sasl_conn_t *conn,
190 				     const char **propnames);
191 	struct propctx *(*sasl_auxprop_getctxPtr)(sasl_conn_t *conn);
192 	void (*sasl_erasebufferPtr)(char *pass, unsigned len);
193 	struct propctx *(*prop_newPtr)(unsigned estimate);
194 	int (*prop_dupPtr)(struct propctx *src_ctx, struct propctx **dst_ctx);
195 	const struct propval *(*prop_getPtr)(struct propctx *ctx);
196 	int (*prop_getnamesPtr)(struct propctx *ctx, const char **names,
197 		  struct propval *vals);
198 	void (*prop_clearPtr)(struct propctx *ctx, int requests);
199 	void (*prop_erasePtr)(struct propctx *ctx, const char *name);
200 	void (*prop_disposePtr)(struct propctx **ctx);
201 	int (*prop_formatPtr)(struct propctx *ctx, const char *sep, int seplen,
202 		char *outbuf, unsigned outmax, unsigned *outlen);
203 	int (*prop_setPtr)(struct propctx *ctx, const char *name,
204 	     const char *value, int vallen);
205 	int (*prop_setvalsPtr)(struct propctx *ctx, const char *name,
206 		 const char **values);
207 	int (*_sasl_add_stringPtr)(char **out, int *alloclen, int *outlen, const char *add);
208 	int (*_buf_allocPtr)(char **rwbuf, unsigned *curlen, unsigned newlen);
209 	void (*_sasl_get_errorbufPtr)(sasl_conn_t *conn, char ***bufhdl, unsigned **lenhdl);
210 
211 } GlobalsRec;
212 
213 typedef struct
214 {
215 	sasl_malloc_t *custMalloc;
216 	sasl_calloc_t *custCalloc;
217 	sasl_realloc_t *custRealloc;
218 	sasl_free_t *custFree;
219 
220 	sasl_mutex_alloc_t *custMutexNew;
221 	sasl_mutex_lock_t *custMutexLock;
222 	sasl_mutex_unlock_t *custMutexUnlock;
223 	sasl_mutex_free_t *custMutexDispose;
224 } GlobalParamsRec;
225 
226 typedef struct
227 {
228 	sasl_conn_t			*ctx;
229 	sasl_callback_t		*cbk;
230 } cfm_sasl_conn_t;
231 
232 GlobalsRec	saslcfmglob;						//	The globals
233 GlobalParamsRec saslcfmglobp;
234 
235 // From Apple sample code... (CarbonLib SDK, CFM->MachO->CFM)
236 //
237 //	This function allocates a block of CFM glue code which contains the instructions to call CFM routines
238 //
MachOFunctionPointerForCFMFunctionPointer(void * cfmfp)239 void	*MachOFunctionPointerForCFMFunctionPointer( void *cfmfp )
240 {
241 	UInt32 template[6] = {0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420};
242     UInt32	*mfp = (UInt32*) NewPtr( sizeof(template) );		//	Must later dispose of allocated memory
243     mfp[0] = template[0] | ((UInt32)cfmfp >> 16);
244     mfp[1] = template[1] | ((UInt32)cfmfp & 0xFFFF);
245     mfp[2] = template[2];
246     mfp[3] = template[3];
247     mfp[4] = template[4];
248     mfp[5] = template[5];
249     MakeDataExecutable( mfp, sizeof(template) );
250     return( mfp );
251 }
252 
GetCFMCallbacks(const sasl_callback_t * callbacks)253 sasl_callback_t *GetCFMCallbacks(const sasl_callback_t *callbacks)
254 {
255 	int cbksize = 0;
256 	const sasl_callback_t *cbk = callbacks;
257 	sasl_callback_t *ncbk, *new_callbacks;
258 	while (cbk->id) {
259 		cbksize++; cbk++;
260 	}
261 	cbksize++; cbk = callbacks;
262 
263 	ncbk = new_callbacks = (sasl_callback_t *)NewPtr(cbksize * sizeof(sasl_callback_t));
264 	if (!ncbk) return nil;
265 	while (cbksize--) {
266 		ncbk->id = cbk->id;
267 		ncbk->context = cbk->context;
268 		if (cbk->proc)
269 			ncbk->proc = MachOFunctionPointerForCFMFunctionPointer(cbk->proc);
270 		else ncbk->proc = nil;
271 		ncbk++; cbk++;
272 	}
273 	return new_callbacks;
274 }
275 
DisposeCFMCallbacks(sasl_callback_t * callbacks)276 void DisposeCFMCallbacks(sasl_callback_t *callbacks)
277 {
278 	sasl_callback_t *cbk = callbacks;
279 	if (!cbk) return;
280 	while (cbk->id) {
281 		if (cbk->proc) DisposePtr((Ptr)cbk->proc);
282 		cbk++;
283 	}
284 	DisposePtr((Ptr)callbacks);
285 }
286 
287 int _cfmsasl_common_init(const sasl_callback_t *callbacks, int isServer, const char *appname);
288 
_cfmsasl_common_init(const sasl_callback_t * callbacks,int isServer,const char * appname)289 int _cfmsasl_common_init(const sasl_callback_t *callbacks, int isServer, const char *appname)
290 {
291 	int (*SASLClientInitPtr)(const sasl_callback_t *callbacks);
292 	int (*SASLServerInitPtr)(const sasl_callback_t *callbacks, const char *appname);
293 	int result = SASL_NOMEM;
294 
295   if (!_cfmsasl_initted) {
296 // The skeleton for this code originally came from the CFM->MachO->CFM sample
297 // provided by Aple with the Carbon SDK. It shows how to use CFBundle to call MachO
298 // libraries from CFM and how to encapsulate callbacks into CFM.
299 	memset( &saslcfmglob, 0, sizeof(GlobalsRec) );						//	Initialize the globals
300 
301 	//	Make a CFURLRef from the CFString representation of the bundle's path.
302 	//	See the Core Foundation URL Services chapter for details.
303 	saslcfmglob.bundleURL	= CFURLCreateWithFileSystemPath(
304 				nil, 										 //	workaround for Radar # 2452789
305 				CFSTR("/Library/Frameworks/SASL2.framework"), //	hard coded path for sample
306 				0,
307 				true );
308 	if ( saslcfmglob.bundleURL != NULL )
309 
310 	// Make a bundle instance using the URLRef.
311 	saslcfmglob.myBundle	= CFBundleCreate(
312 				NULL /* kCFAllocatorDefault */, 			//	workaround for Radar # 2452789
313 				saslcfmglob.bundleURL );
314 
315 	if ( saslcfmglob.myBundle && CFBundleLoadExecutable( saslcfmglob.myBundle )) {	//	Try to load the executable from my bundle.
316 
317 		// Now that the code is loaded, search for the functions we want by name.
318 		saslcfmglob.SASLClientNewPtr = (void*)CFBundleGetFunctionPointerForName(
319 						saslcfmglob.myBundle, CFSTR("sasl_client_new") );
320 
321 		saslcfmglob.SASLClientStartPtr = (void*)CFBundleGetFunctionPointerForName(
322 						saslcfmglob.myBundle, CFSTR("sasl_client_start") );
323 
324 		saslcfmglob.SASLClientStepPtr = (void*)CFBundleGetFunctionPointerForName(
325 						saslcfmglob.myBundle, CFSTR("sasl_client_step") );
326 
327 		saslcfmglob.SASLErrStringPtr = (void*)CFBundleGetFunctionPointerForName(
328 						saslcfmglob.myBundle, CFSTR("sasl_errstring") );
329 
330 		saslcfmglob.sasl_errdetailPtr = (void*)CFBundleGetFunctionPointerForName(
331 						saslcfmglob.myBundle, CFSTR("sasl_errdetail") );
332 
333 		saslcfmglob.SASLGetPropPtr = (void*)CFBundleGetFunctionPointerForName(
334 						saslcfmglob.myBundle, CFSTR("sasl_getprop") );
335 
336 		saslcfmglob.SASLSetPropPtr = (void*)CFBundleGetFunctionPointerForName(
337 						saslcfmglob.myBundle, CFSTR("sasl_setprop") );
338 
339 		saslcfmglob.SASLIdlePtr = (void*)CFBundleGetFunctionPointerForName(
340 						saslcfmglob.myBundle, CFSTR("sasl_idle") );
341 
342 		saslcfmglob.SASLEncodePtr = (void*)CFBundleGetFunctionPointerForName(
343 						saslcfmglob.myBundle, CFSTR("sasl_encode") );
344 
345 		saslcfmglob.SASLEncodeVPtr = (void*)CFBundleGetFunctionPointerForName(
346 						saslcfmglob.myBundle, CFSTR("sasl_encodev") );
347 
348 		saslcfmglob.SASLDecodePtr = (void*)CFBundleGetFunctionPointerForName(
349 						saslcfmglob.myBundle, CFSTR("sasl_decode") );
350 
351 		saslcfmglob.SASLDisposePtr = (void*)CFBundleGetFunctionPointerForName(
352 						saslcfmglob.myBundle, CFSTR("sasl_dispose") );
353 
354 		saslcfmglob.SASLDonePtr = (void*)CFBundleGetFunctionPointerForName(
355 						saslcfmglob.myBundle, CFSTR("sasl_done") );
356 
357 		saslcfmglob.SASLSetAllocPtr = (void*)CFBundleGetFunctionPointerForName(
358 						saslcfmglob.myBundle, CFSTR("sasl_set_alloc") );
359 
360 		saslcfmglob.sasl_encode64Ptr = (void*)CFBundleGetFunctionPointerForName(
361 						saslcfmglob.myBundle, CFSTR("sasl_encode64") );
362 
363 		saslcfmglob.sasl_decode64Ptr = (void*)CFBundleGetFunctionPointerForName(
364 						saslcfmglob.myBundle, CFSTR("sasl_decode64") );
365 
366 		saslcfmglob.sasl_mkchalPtr = (void*)CFBundleGetFunctionPointerForName(
367 						saslcfmglob.myBundle, CFSTR("sasl_mkchal") );
368 
369 		saslcfmglob.sasl_utf8verifyPtr = (void*)CFBundleGetFunctionPointerForName(
370 						saslcfmglob.myBundle, CFSTR("sasl_utf8verify") );
371 
372 		saslcfmglob.sasl_churnPtr = (void*)CFBundleGetFunctionPointerForName(
373 						saslcfmglob.myBundle, CFSTR("sasl_churn") );
374 
375 		saslcfmglob.sasl_randPtr = (void*)CFBundleGetFunctionPointerForName(
376 						saslcfmglob.myBundle, CFSTR("sasl_rand") );
377 
378 		saslcfmglob.sasl_randseedPtr = (void*)CFBundleGetFunctionPointerForName(
379 						saslcfmglob.myBundle, CFSTR("sasl_randseed") );
380 
381 		saslcfmglob.sasl_randcreatePtr = (void*)CFBundleGetFunctionPointerForName(
382 						saslcfmglob.myBundle, CFSTR("sasl_randcreate") );
383 
384 		saslcfmglob.sasl_randfreePtr = (void*)CFBundleGetFunctionPointerForName(
385 						saslcfmglob.myBundle, CFSTR("sasl_randfree") );
386 
387 		saslcfmglob.SASLSetMutexPtr = (void*)CFBundleGetFunctionPointerForName(
388 						saslcfmglob.myBundle, CFSTR("sasl_set_mutex") );
389 
390 		saslcfmglob.SASLServerNewPtr = (void*)CFBundleGetFunctionPointerForName(
391 						saslcfmglob.myBundle, CFSTR("sasl_server_new") );
392 
393 		saslcfmglob.SASLServerStartPtr = (void*)CFBundleGetFunctionPointerForName(
394 						saslcfmglob.myBundle, CFSTR("sasl_server_start") );
395 
396 		saslcfmglob.SASLServerStepPtr = (void*)CFBundleGetFunctionPointerForName(
397 						saslcfmglob.myBundle, CFSTR("sasl_server_step") );
398 
399 		saslcfmglob.sasl_listmechPtr = (void*)CFBundleGetFunctionPointerForName(
400 						saslcfmglob.myBundle, CFSTR("sasl_listmech") );
401 
402 		saslcfmglob.sasl_checkpassPtr = (void*)CFBundleGetFunctionPointerForName(
403 						saslcfmglob.myBundle, CFSTR("sasl_checkpass") );
404 
405 		saslcfmglob.sasl_setpassPtr = (void*)CFBundleGetFunctionPointerForName(
406 						saslcfmglob.myBundle, CFSTR("sasl_setpass") );
407 
408 		saslcfmglob.sasl_user_existsPtr = (void*)CFBundleGetFunctionPointerForName(
409 						saslcfmglob.myBundle, CFSTR("sasl_user_exists") );
410 
411 		saslcfmglob.sasl_checkapopPtr = (void*)CFBundleGetFunctionPointerForName(
412 						saslcfmglob.myBundle, CFSTR("sasl_checkapop") );
413 
414 		saslcfmglob.sasl_auxprop_requestPtr = (void*)CFBundleGetFunctionPointerForName(
415 						saslcfmglob.myBundle, CFSTR("sasl_auxprop_request") );
416 
417 		saslcfmglob.sasl_auxprop_getctxPtr = (void*)CFBundleGetFunctionPointerForName(
418 						saslcfmglob.myBundle, CFSTR("sasl_auxprop_getctx") );
419 
420 		saslcfmglob.sasl_erasebufferPtr = (void*)CFBundleGetFunctionPointerForName(
421 						saslcfmglob.myBundle, CFSTR("sasl_erasebuffer") );
422 
423 		saslcfmglob.prop_newPtr = (void*)CFBundleGetFunctionPointerForName(
424 						saslcfmglob.myBundle, CFSTR("prop_new") );
425 
426 		saslcfmglob.prop_dupPtr = (void*)CFBundleGetFunctionPointerForName(
427 						saslcfmglob.myBundle, CFSTR("prop_dup") );
428 
429 		saslcfmglob.prop_getPtr = (void*)CFBundleGetFunctionPointerForName(
430 						saslcfmglob.myBundle, CFSTR("prop_get") );
431 
432 		saslcfmglob.prop_getnamesPtr = (void*)CFBundleGetFunctionPointerForName(
433 						saslcfmglob.myBundle, CFSTR("prop_getnames") );
434 
435 		saslcfmglob.prop_clearPtr = (void*)CFBundleGetFunctionPointerForName(
436 						saslcfmglob.myBundle, CFSTR("prop_clear") );
437 
438 		saslcfmglob.prop_erasePtr = (void*)CFBundleGetFunctionPointerForName(
439 						saslcfmglob.myBundle, CFSTR("prop_erase") );
440 
441 		saslcfmglob.prop_disposePtr = (void*)CFBundleGetFunctionPointerForName(
442 						saslcfmglob.myBundle, CFSTR("prop_dispose") );
443 
444 		saslcfmglob.prop_formatPtr = (void*)CFBundleGetFunctionPointerForName(
445 						saslcfmglob.myBundle, CFSTR("prop_format") );
446 
447 		saslcfmglob.prop_setPtr = (void*)CFBundleGetFunctionPointerForName(
448 						saslcfmglob.myBundle, CFSTR("prop_set") );
449 
450 		saslcfmglob.prop_setvalsPtr = (void*)CFBundleGetFunctionPointerForName(
451 						saslcfmglob.myBundle, CFSTR("prop_setvals") );
452 
453 /* These are internal functions used by our sasl_seterror */
454 		saslcfmglob._sasl_add_stringPtr = (void*)CFBundleGetFunctionPointerForName(
455 						saslcfmglob.myBundle, CFSTR("_sasl_add_string") );
456 
457 		saslcfmglob._buf_allocPtr = (void*)CFBundleGetFunctionPointerForName(
458 						saslcfmglob.myBundle, CFSTR("_buf_alloc") );
459 
460 		saslcfmglob._sasl_get_errorbufPtr = (void*)CFBundleGetFunctionPointerForName(
461 						saslcfmglob.myBundle, CFSTR("_sasl_get_errorbuf") );
462 
463 		if (!_cfmsasl_haveCustomAlloc) {
464 			saslcfmglobp.custMalloc = MachOFunctionPointerForCFMFunctionPointer(malloc);
465 			saslcfmglobp.custCalloc = MachOFunctionPointerForCFMFunctionPointer(calloc);
466 			saslcfmglobp.custRealloc = MachOFunctionPointerForCFMFunctionPointer(realloc);
467 			saslcfmglobp.custFree = MachOFunctionPointerForCFMFunctionPointer(free);
468 
469 			_cfmsasl_haveCustomAlloc = 1;
470 		}
471 
472 		saslcfmglob.SASLSetAllocPtr(saslcfmglobp.custMalloc, saslcfmglobp.custCalloc,
473 									saslcfmglobp.custRealloc, saslcfmglobp.custFree);
474 
475 		if (_cfmsasl_haveCustomMutex)
476 			saslcfmglob.SASLSetMutexPtr(saslcfmglobp.custMutexNew, saslcfmglobp.custMutexLock,
477 										saslcfmglobp.custMutexUnlock, saslcfmglobp.custMutexDispose);
478 
479 	} else if (saslcfmglob.myBundle) {
480 		CFRelease(saslcfmglob.myBundle);
481 		saslcfmglob.myBundle = nil;
482 	}
483 
484 	if (saslcfmglob.bundleURL && !saslcfmglob.myBundle) {
485 		CFRelease(saslcfmglob.bundleURL);
486 		saslcfmglob.bundleURL = nil;
487 	}
488 
489 	if (saslcfmglob.myBundle)
490 		_cfmsasl_initted = 1;
491   }
492 
493 	if (_cfmsasl_initted) {
494 		if (isServer) {
495 			SASLServerInitPtr = (void*)CFBundleGetFunctionPointerForName(
496 						saslcfmglob.myBundle, CFSTR("sasl_server_init") );
497 			if (SASLServerInitPtr != nil) {
498 	    		sasl_callback_t *new_callbacks = NULL;
499 				if (callbacks)
500 					new_callbacks = GetCFMCallbacks(callbacks);
501 				result = SASLServerInitPtr(new_callbacks, appname);
502 				saslcfmglob.serverCallbacks = new_callbacks;
503 			}
504 		} else {
505 			SASLClientInitPtr = (void*)CFBundleGetFunctionPointerForName(
506 						saslcfmglob.myBundle, CFSTR("sasl_client_init") );
507 			if (SASLClientInitPtr != nil) {
508 	    		sasl_callback_t *new_callbacks = NULL;
509 				if (callbacks)
510 					new_callbacks = GetCFMCallbacks(callbacks);
511 				result = SASLClientInitPtr(new_callbacks);
512 				saslcfmglob.clientCallbacks = new_callbacks;
513 			}
514 		}
515 	}
516 	return result;
517 }
518 
sasl_server_init(const sasl_callback_t * callbacks,const char * appname)519 int sasl_server_init(const sasl_callback_t *callbacks,
520 				 const char *appname)
521 {
522 	return _cfmsasl_common_init(callbacks, true, appname);
523 }
524 
sasl_client_init(const sasl_callback_t * callbacks)525 int sasl_client_init(const sasl_callback_t *callbacks)
526 {
527 	return _cfmsasl_common_init(callbacks, false, nil);
528 }
529 
sasl_done(void)530 void sasl_done(void)
531 {
532 	if (!_cfmsasl_initted)
533 		return;
534 	if (!saslcfmglob.SASLDonePtr) return;
535 
536 	saslcfmglob.SASLDonePtr();
537 	DisposeCFMCallbacks(saslcfmglob.clientCallbacks);
538 	DisposeCFMCallbacks(saslcfmglob.serverCallbacks);
539 	CFBundleUnloadExecutable(saslcfmglob.myBundle);
540 	CFRelease(saslcfmglob.myBundle);
541 	CFRelease(saslcfmglob.bundleURL);
542 	saslcfmglob.myBundle = NULL;
543 	saslcfmglob.bundleURL = NULL;
544 
545         _cfmsasl_initted = 0;
546 }
547 
sasl_client_new(const char * service,const char * serverFQDN,const char * iplocalport,const char * ipremoteport,const sasl_callback_t * prompt_supp,unsigned flags,sasl_conn_t ** pconn)548 int sasl_client_new (const char *service,
549 						const char *serverFQDN,
550 						const char *iplocalport,
551 						const char *ipremoteport,
552 						const sasl_callback_t *prompt_supp,
553 						unsigned flags,
554 						sasl_conn_t **pconn)
555 {
556 	sasl_callback_t *new_ps = NULL;
557 	int result;
558 	cfm_sasl_conn_t *myconn;
559 
560 	if (!_cfmsasl_initted)
561 		return SASL_NOMEM;
562 	if (!saslcfmglob.SASLClientNewPtr) return SASL_NOMEM;
563 
564 	if (prompt_supp)
565 		new_ps = GetCFMCallbacks(prompt_supp);
566 
567 // this is commented out because sasl.h incorrectly described the api
568 //	if (*pconn)
569 //		DisposeCFMCallbacks(((cfm_sasl_conn_t *)*pconn)->cbk);
570 //	else {
571 	myconn = (cfm_sasl_conn_t *) NewPtr(sizeof(cfm_sasl_conn_t));
572 	if (myconn == NULL) {
573 		return SASL_NOMEM;
574 	}
575 
576 	myconn->ctx = NULL;
577 //	}
578 
579 	result = saslcfmglob.SASLClientNewPtr(service, serverFQDN, iplocalport,
580 				ipremoteport, new_ps, flags,
581 				&(myconn->ctx));
582 	myconn->cbk = new_ps;
583 
584 	*pconn = (sasl_conn_t *)myconn;
585 
586 	return result;
587 }
588 
sasl_server_new(const char * service,const char * serverFQDN,const char * user_realm,const char * iplocalport,const char * ipremoteport,const sasl_callback_t * callbacks,unsigned flags,sasl_conn_t ** pconn)589 int sasl_server_new (const char *service,
590 						const char *serverFQDN,
591 						const char *user_realm,
592 						const char *iplocalport,
593 						const char *ipremoteport,
594 						const sasl_callback_t *callbacks,
595 						unsigned flags,
596 						sasl_conn_t **pconn)
597 {
598 	sasl_callback_t *new_ps = NULL;
599 	int result;
600 
601 	if (!_cfmsasl_initted)
602 		return SASL_NOMEM;
603 	if (!saslcfmglob.SASLServerNewPtr) return SASL_NOMEM;
604 
605 	if (callbacks)
606 		new_ps = GetCFMCallbacks(callbacks);
607 	*pconn = (sasl_conn_t *)NewPtr(sizeof(cfm_sasl_conn_t));
608 	((cfm_sasl_conn_t *)*pconn)->ctx = nil;
609 
610 	result = saslcfmglob.SASLServerNewPtr(service, serverFQDN, user_realm,
611 				iplocalport, ipremoteport, new_ps, flags,
612 				&((cfm_sasl_conn_t *)*pconn)->ctx);
613 	((cfm_sasl_conn_t *)*pconn)->cbk = new_ps;
614 
615 	return result;
616 }
617 
sasl_dispose(sasl_conn_t ** pconn)618 void sasl_dispose(sasl_conn_t **pconn)
619 {
620 	if (!_cfmsasl_initted)
621 		return;
622 	if (!saslcfmglob.SASLDisposePtr) return;
623 
624 	if (!pconn) return;
625 	if (!*pconn) return;
626 
627 	saslcfmglob.SASLDisposePtr(&((cfm_sasl_conn_t *)*pconn)->ctx);
628 	DisposeCFMCallbacks(((cfm_sasl_conn_t *)*pconn)->cbk);
629 	DisposePtr((Ptr)*pconn);
630 	*pconn = NULL;
631 }
632 
sasl_client_start(sasl_conn_t * conn,const char * mechlist,sasl_interact_t ** prompt_need,const char ** clientout,unsigned * clientoutlen,const char ** mech)633 int sasl_client_start (sasl_conn_t *conn,
634 						const char *mechlist,
635 						sasl_interact_t **prompt_need,
636 						const char **clientout,
637 						unsigned *clientoutlen,
638 						const char **mech)
639 {
640 	if (!_cfmsasl_initted)
641 		return SASL_NOMEM;
642 	if (!saslcfmglob.SASLClientStartPtr) return SASL_NOMEM;
643 
644 	return saslcfmglob.SASLClientStartPtr(((cfm_sasl_conn_t *)conn)->ctx, mechlist,
645 				prompt_need, clientout, clientoutlen, mech);
646 }
647 
sasl_client_step(sasl_conn_t * conn,const char * serverin,unsigned serverinlen,sasl_interact_t ** prompt_need,const char ** clientout,unsigned * clientoutlen)648 int sasl_client_step (sasl_conn_t *conn,
649 						const char *serverin,
650 						unsigned serverinlen,
651 						sasl_interact_t **prompt_need,
652 						const char **clientout,
653 						unsigned *clientoutlen)
654 {
655 	if (!_cfmsasl_initted)
656 		return SASL_NOMEM;
657 	if (!saslcfmglob.SASLClientStepPtr) return SASL_NOMEM;
658 
659 	return saslcfmglob.SASLClientStepPtr(((cfm_sasl_conn_t *)conn)->ctx, serverin,
660 							serverinlen, prompt_need, clientout, clientoutlen);
661 }
662 
sasl_errstring(int saslerr,const char * langlist,const char ** outlang)663 const char *sasl_errstring(int saslerr,
664 							const char *langlist,
665 							const char **outlang)
666 {
667 	if (!_cfmsasl_initted)
668 		return NULL;
669 	if (!saslcfmglob.SASLErrStringPtr) return NULL;
670 
671 	return saslcfmglob.SASLErrStringPtr(saslerr, langlist, outlang);
672 }
673 
sasl_errdetail(sasl_conn_t * conn)674 const char *sasl_errdetail(sasl_conn_t *conn)
675 {
676 	if (!_cfmsasl_initted)
677 		return NULL;
678 	if (!saslcfmglob.sasl_errdetailPtr) return NULL;
679 
680 	return saslcfmglob.sasl_errdetailPtr(((cfm_sasl_conn_t *)conn)->ctx);
681 }
682 
sasl_getprop(sasl_conn_t * conn,int propnum,const void ** pvalue)683 int sasl_getprop(sasl_conn_t *conn, int propnum, const void **pvalue)
684 {
685 	if (!_cfmsasl_initted)
686 		return SASL_NOMEM;
687 	if (!saslcfmglob.SASLGetPropPtr) return SASL_NOMEM;
688 
689 	return saslcfmglob.SASLGetPropPtr(((cfm_sasl_conn_t *)conn)->ctx, propnum, pvalue);
690 }
691 
sasl_setprop(sasl_conn_t * conn,int propnum,const void * value)692 int sasl_setprop(sasl_conn_t *conn,
693 					int propnum,
694 					const void *value)
695 {
696 	if (!_cfmsasl_initted)
697 		return SASL_NOMEM;
698 	if (!saslcfmglob.SASLSetPropPtr) return SASL_NOMEM;
699 
700 	return saslcfmglob.SASLSetPropPtr(((cfm_sasl_conn_t *)conn)->ctx, propnum, value);
701 }
702 
sasl_idle(sasl_conn_t * conn)703 int sasl_idle(sasl_conn_t *conn)
704 {
705 	if (!_cfmsasl_initted)
706 		return SASL_NOMEM;
707 	if (!saslcfmglob.SASLIdlePtr) return SASL_NOMEM;
708 
709 	return saslcfmglob.SASLIdlePtr(((cfm_sasl_conn_t *)conn)->ctx);
710 }
711 
sasl_encode(sasl_conn_t * conn,const char * input,unsigned inputlen,const char ** output,unsigned * outputlen)712 int sasl_encode(sasl_conn_t *conn,
713 				const char *input, unsigned inputlen,
714 				const char **output, unsigned *outputlen)
715 {
716 	if (!_cfmsasl_initted)
717 		return SASL_NOMEM;
718 	if (!saslcfmglob.SASLEncodePtr) return SASL_NOMEM;
719 
720 	return saslcfmglob.SASLEncodePtr(((cfm_sasl_conn_t *)conn)->ctx, input, inputlen,
721 											output, outputlen);
722 }
723 
sasl_encodev(sasl_conn_t * conn,const struct iovec * invec,unsigned numiov,const char ** output,unsigned * outputlen)724 int sasl_encodev(sasl_conn_t *conn,
725 			     const struct iovec *invec, unsigned numiov,
726 			     const char **output, unsigned *outputlen)
727 {
728 	if (!_cfmsasl_initted)
729 		return SASL_NOMEM;
730 	if (!saslcfmglob.SASLEncodeVPtr) return SASL_NOMEM;
731 
732 	return saslcfmglob.SASLEncodeVPtr(((cfm_sasl_conn_t *)conn)->ctx, invec, numiov,
733 											output, outputlen);
734 }
735 
sasl_decode(sasl_conn_t * conn,const char * input,unsigned inputlen,const char ** output,unsigned * outputlen)736 int sasl_decode(sasl_conn_t *conn,
737 				const char *input, unsigned inputlen,
738 				const char **output, unsigned *outputlen)
739 {
740 	if (!_cfmsasl_initted)
741 		return SASL_NOMEM;
742 	if (!saslcfmglob.SASLDecodePtr) return SASL_NOMEM;
743 
744 	return saslcfmglob.SASLDecodePtr(((cfm_sasl_conn_t *)conn)->ctx, input, inputlen,
745 											output, outputlen);
746 }
747 
sasl_decode64(const char * in,unsigned inlen,char * out,unsigned outmax,unsigned * outlen)748 int sasl_decode64(const char *in, unsigned inlen,
749 			      char *out, unsigned outmax, unsigned *outlen)
750 {
751 	if (!_cfmsasl_initted)
752 		return SASL_NOMEM;
753 	if (!saslcfmglob.sasl_decode64Ptr) return SASL_NOMEM;
754 
755 	return saslcfmglob.sasl_decode64Ptr(in, inlen, out, outmax, outlen);
756 }
757 
sasl_encode64(const char * in,unsigned inlen,char * out,unsigned outmax,unsigned * outlen)758 int sasl_encode64(const char *in, unsigned inlen,
759 			      char *out, unsigned outmax, unsigned *outlen)
760 {
761 	if (!_cfmsasl_initted)
762 		return SASL_NOMEM;
763 	if (!saslcfmglob.sasl_encode64Ptr) return SASL_NOMEM;
764 
765 	return saslcfmglob.sasl_encode64Ptr(in, inlen, out, outmax, outlen);
766 }
767 
sasl_set_alloc(sasl_malloc_t * ma,sasl_calloc_t * ca,sasl_realloc_t * rea,sasl_free_t * fr)768 void sasl_set_alloc(sasl_malloc_t *ma, sasl_calloc_t *ca, sasl_realloc_t *rea, sasl_free_t *fr)
769 {
770 	if (_cfmsasl_haveCustomAlloc) {
771 		DisposePtr((Ptr)saslcfmglobp.custMalloc);
772 		DisposePtr((Ptr)saslcfmglobp.custCalloc);
773 		DisposePtr((Ptr)saslcfmglobp.custRealloc);
774 		DisposePtr((Ptr)saslcfmglobp.custFree);
775 	}
776 	saslcfmglobp.custMalloc = MachOFunctionPointerForCFMFunctionPointer(ma);
777 	saslcfmglobp.custCalloc = MachOFunctionPointerForCFMFunctionPointer(ca);
778 	saslcfmglobp.custRealloc = MachOFunctionPointerForCFMFunctionPointer(rea);
779 	saslcfmglobp.custFree = MachOFunctionPointerForCFMFunctionPointer(fr);
780 	_cfmsasl_haveCustomAlloc = 1;
781 }
782 
sasl_mkchal(sasl_conn_t * conn,char * buf,unsigned maxlen,unsigned hostflag)783 int sasl_mkchal(sasl_conn_t *conn, char *buf,
784 			    unsigned maxlen, unsigned hostflag)
785 {
786 	if (!_cfmsasl_initted)
787 		return SASL_NOMEM;
788 	if (!saslcfmglob.sasl_mkchalPtr) return SASL_NOMEM;
789 
790 	return saslcfmglob.sasl_mkchalPtr(((cfm_sasl_conn_t *)conn)->ctx, buf, maxlen, hostflag);
791 }
792 
sasl_utf8verify(const char * str,unsigned len)793 int sasl_utf8verify(const char *str, unsigned len)
794 {
795 	if (!_cfmsasl_initted)
796 		return SASL_NOMEM;
797 	if (!saslcfmglob.sasl_utf8verifyPtr) return SASL_NOMEM;
798 
799 	return saslcfmglob.sasl_utf8verifyPtr(str, len);
800 }
801 
sasl_churn(sasl_rand_t * rpool,const char * data,unsigned len)802 void sasl_churn(sasl_rand_t *rpool,
803 			    const char *data,
804 			    unsigned len)
805 {
806 	if (!_cfmsasl_initted)
807 		return;
808 	if (!saslcfmglob.sasl_churnPtr) return;
809 
810 	saslcfmglob.sasl_churnPtr(rpool, data, len);
811 }
812 
sasl_rand(sasl_rand_t * rpool,char * buf,unsigned len)813 void sasl_rand(sasl_rand_t *rpool,
814 			   char *buf,
815 			   unsigned len)
816 {
817 	if (!_cfmsasl_initted)
818 		return;
819 	if (!saslcfmglob.sasl_randPtr) return;
820 
821 	saslcfmglob.sasl_randPtr(rpool, buf, len);
822 }
823 
sasl_randseed(sasl_rand_t * rpool,const char * seed,unsigned len)824 void sasl_randseed(sasl_rand_t *rpool,
825 			       const char *seed,
826 			       unsigned len)
827 {
828 	if (!_cfmsasl_initted)
829 		return;
830 	if (!saslcfmglob.sasl_randseedPtr) return;
831 
832 	saslcfmglob.sasl_randseedPtr(rpool, seed, len);
833 }
834 
sasl_randfree(sasl_rand_t ** rpool)835 void sasl_randfree(sasl_rand_t **rpool)
836 {
837 	if (!_cfmsasl_initted)
838 		return;
839 	if (!saslcfmglob.sasl_randfreePtr) return;
840 
841 	saslcfmglob.sasl_randfreePtr(rpool);
842 }
843 
sasl_randcreate(sasl_rand_t ** rpool)844 int sasl_randcreate(sasl_rand_t **rpool)
845 {
846 	if (!_cfmsasl_initted)
847 		return SASL_NOMEM;
848 	if (!saslcfmglob.sasl_randcreatePtr) return SASL_NOMEM;
849 
850 	return saslcfmglob.sasl_randcreatePtr(rpool);
851 }
852 
sasl_set_mutex(sasl_mutex_alloc_t * mn,sasl_mutex_lock_t * ml,sasl_mutex_unlock_t * mu,sasl_mutex_free_t * md)853 void sasl_set_mutex(sasl_mutex_alloc_t *mn, sasl_mutex_lock_t *ml,
854                                 sasl_mutex_unlock_t *mu, sasl_mutex_free_t *md)
855 {
856 	if (_cfmsasl_haveCustomMutex) {
857 		DisposePtr((Ptr)saslcfmglobp.custMutexNew);
858 		DisposePtr((Ptr)saslcfmglobp.custMutexLock);
859 		DisposePtr((Ptr)saslcfmglobp.custMutexUnlock);
860 		DisposePtr((Ptr)saslcfmglobp.custMutexDispose);
861 	}
862 	saslcfmglobp.custMutexNew = MachOFunctionPointerForCFMFunctionPointer(mn);
863 	saslcfmglobp.custMutexLock = MachOFunctionPointerForCFMFunctionPointer(ml);
864 	saslcfmglobp.custMutexUnlock = MachOFunctionPointerForCFMFunctionPointer(mu);
865 	saslcfmglobp.custMutexDispose = MachOFunctionPointerForCFMFunctionPointer(md);
866 	_cfmsasl_haveCustomMutex = 1;
867 }
868 
sasl_listmech(sasl_conn_t * conn,const char * user,const char * prefix,const char * sep,const char * suffix,const char ** result,unsigned * plen,int * pcount)869 int sasl_listmech(sasl_conn_t *conn,
870 			      const char *user,
871 			      const char *prefix,
872 			      const char *sep,
873 			      const char *suffix,
874 			      const char **result,
875 			      unsigned *plen,
876 			      int *pcount)
877 {
878 	if (!_cfmsasl_initted)
879 		return SASL_NOMEM;
880 	if (!saslcfmglob.sasl_listmechPtr) return SASL_NOMEM;
881 
882 	return saslcfmglob.sasl_listmechPtr(((cfm_sasl_conn_t *)conn)->ctx, user, prefix, sep,
883 											suffix, result, plen, pcount);
884 }
885 
sasl_server_start(sasl_conn_t * conn,const char * mech,const char * clientin,unsigned clientinlen,const char ** serverout,unsigned * serveroutlen)886 int sasl_server_start(sasl_conn_t *conn,
887 				  const char *mech,
888 				  const char *clientin,
889 				  unsigned clientinlen,
890 				  const char **serverout,
891 				  unsigned *serveroutlen)
892 {
893 	if (!_cfmsasl_initted)
894 		return SASL_NOMEM;
895 	if (!saslcfmglob.SASLServerStartPtr) return SASL_NOMEM;
896 
897 	return saslcfmglob.SASLServerStartPtr(((cfm_sasl_conn_t *)conn)->ctx, mech, clientin,
898 											clientinlen, serverout, serveroutlen);
899 }
900 
sasl_server_step(sasl_conn_t * conn,const char * clientin,unsigned clientinlen,const char ** serverout,unsigned * serveroutlen)901 int sasl_server_step(sasl_conn_t *conn,
902 		     const char *clientin,
903 		     unsigned clientinlen,
904 		     const char **serverout,
905 		     unsigned *serveroutlen)
906 {
907 	if (!_cfmsasl_initted)
908 		return SASL_NOMEM;
909 	if (!saslcfmglob.SASLServerStepPtr) return SASL_NOMEM;
910 
911 	return saslcfmglob.SASLServerStepPtr(((cfm_sasl_conn_t *)conn)->ctx, clientin, clientinlen,
912 											serverout, serveroutlen);
913 }
914 
sasl_checkpass(sasl_conn_t * conn,const char * user,unsigned userlen,const char * pass,unsigned passlen)915 int sasl_checkpass(sasl_conn_t *conn,
916 			       const char *user,
917 			       unsigned userlen,
918 			       const char *pass,
919 			       unsigned passlen)
920 {
921 	if (!_cfmsasl_initted)
922 		return SASL_NOMEM;
923 	if (!saslcfmglob.sasl_checkpassPtr) return SASL_NOMEM;
924 
925 	return saslcfmglob.sasl_checkpassPtr(((cfm_sasl_conn_t *)conn)->ctx, user, userlen, pass,
926 											passlen);
927 }
928 
sasl_user_exists(sasl_conn_t * conn,const char * service,const char * user_realm,const char * user)929 int sasl_user_exists(sasl_conn_t *conn,
930 			 const char *service,
931 		     const char *user_realm,
932 		     const char *user)
933 {
934 	if (!_cfmsasl_initted)
935 		return SASL_NOMEM;
936 	if (!saslcfmglob.sasl_user_existsPtr) return SASL_NOMEM;
937 
938 	return saslcfmglob.sasl_user_existsPtr(((cfm_sasl_conn_t *)conn)->ctx,
939 												service, user_realm, user);
940 }
941 
sasl_setpass(sasl_conn_t * conn,const char * user,const char * pass,unsigned passlen,const char * oldpass,unsigned oldpasslen,unsigned flags)942 int sasl_setpass(sasl_conn_t *conn,
943 		 const char *user,
944 		 const char *pass,
945 		 unsigned passlen,
946 		 const char *oldpass, unsigned oldpasslen,
947 		 unsigned flags)
948 {
949 	if (!_cfmsasl_initted)
950 		return SASL_NOMEM;
951 	if (!saslcfmglob.sasl_setpassPtr) return SASL_NOMEM;
952 
953 	return saslcfmglob.sasl_setpassPtr(((cfm_sasl_conn_t *)conn)->ctx, user, pass,
954 											passlen, oldpass, oldpasslen, flags);
955 }
956 
sasl_checkapop(sasl_conn_t * conn,const char * challenge,unsigned challen,const char * response,unsigned resplen)957 int sasl_checkapop(sasl_conn_t *conn,
958 			       const char *challenge, unsigned challen,
959 			       const char *response, unsigned resplen)
960 {
961 	if (!_cfmsasl_initted)
962 		return SASL_NOMEM;
963 	if (!saslcfmglob.sasl_checkapopPtr) return SASL_NOMEM;
964 
965 	return saslcfmglob.sasl_checkapopPtr(((cfm_sasl_conn_t *)conn)->ctx, challenge, challen,
966 												response, resplen);
967 }
968 
sasl_auxprop_request(sasl_conn_t * conn,const char ** propnames)969 int sasl_auxprop_request(sasl_conn_t *conn,
970 				     const char **propnames)
971 {
972 	if (!_cfmsasl_initted)
973 		return SASL_NOMEM;
974 	if (!saslcfmglob.sasl_auxprop_requestPtr) return SASL_NOMEM;
975 
976 	return saslcfmglob.sasl_auxprop_requestPtr(((cfm_sasl_conn_t *)conn)->ctx, propnames);
977 }
978 
sasl_auxprop_getctx(sasl_conn_t * conn)979 struct propctx *sasl_auxprop_getctx(sasl_conn_t *conn)
980 {
981 	if (!_cfmsasl_initted)
982 		return NULL;
983 	if (!saslcfmglob.sasl_auxprop_getctxPtr) return NULL;
984 
985 	return saslcfmglob.sasl_auxprop_getctxPtr(((cfm_sasl_conn_t *)conn)->ctx);
986 }
987 
sasl_erasebuffer(char * pass,unsigned len)988 void sasl_erasebuffer(char *pass, unsigned len)
989 {
990 	if (!_cfmsasl_initted)
991 		return;
992 	if (!saslcfmglob.sasl_erasebufferPtr) return;
993 
994 	saslcfmglob.sasl_erasebufferPtr(pass, len);
995 }
996 
prop_new(unsigned estimate)997 struct propctx *prop_new(unsigned estimate)
998 {
999 	if (!_cfmsasl_initted)
1000 		return NULL;
1001 	if (!saslcfmglob.prop_newPtr) return NULL;
1002 
1003 	return saslcfmglob.prop_newPtr(estimate);
1004 }
1005 
prop_dup(struct propctx * src_ctx,struct propctx ** dst_ctx)1006 int prop_dup(struct propctx *src_ctx, struct propctx **dst_ctx)
1007 {
1008 	if (!_cfmsasl_initted)
1009 		return SASL_NOMEM;
1010 	if (!saslcfmglob.prop_dupPtr) return SASL_NOMEM;
1011 
1012 	return saslcfmglob.prop_dupPtr(src_ctx, dst_ctx);
1013 }
1014 
prop_get(struct propctx * ctx)1015 const struct propval *prop_get(struct propctx *ctx)
1016 {
1017 	if (!_cfmsasl_initted)
1018 		return NULL;
1019 	if (!saslcfmglob.prop_getPtr) return NULL;
1020 
1021 	return saslcfmglob.prop_getPtr(ctx);
1022 }
1023 
prop_getnames(struct propctx * ctx,const char ** names,struct propval * vals)1024 int prop_getnames(struct propctx *ctx, const char **names,
1025 		  struct propval *vals)
1026 {
1027 	if (!_cfmsasl_initted)
1028 		return SASL_NOMEM;
1029 	if (!saslcfmglob.prop_getnamesPtr) return SASL_NOMEM;
1030 
1031 	return saslcfmglob.prop_getnamesPtr(ctx, names, vals);
1032 }
1033 
prop_clear(struct propctx * ctx,int requests)1034 void prop_clear(struct propctx *ctx, int requests)
1035 {
1036 	if (!_cfmsasl_initted)
1037 		return;
1038 	if (!saslcfmglob.prop_clearPtr) return;
1039 
1040 	saslcfmglob.prop_clearPtr(ctx, requests);
1041 }
1042 
prop_erase(struct propctx * ctx,const char * name)1043 void prop_erase(struct propctx *ctx, const char *name)
1044 {
1045 	if (!_cfmsasl_initted)
1046 		return;
1047 	if (!saslcfmglob.prop_erasePtr) return;
1048 
1049 	saslcfmglob.prop_erasePtr(ctx, name);
1050 }
1051 
prop_dispose(struct propctx ** ctx)1052 void prop_dispose(struct propctx **ctx)
1053 {
1054 	if (!_cfmsasl_initted)
1055 		return;
1056 	if (!saslcfmglob.prop_disposePtr) return;
1057 
1058 	saslcfmglob.prop_disposePtr(ctx);
1059 }
1060 
prop_format(struct propctx * ctx,const char * sep,int seplen,char * outbuf,unsigned outmax,unsigned * outlen)1061 int prop_format(struct propctx *ctx, const char *sep, int seplen,
1062 		char *outbuf, unsigned outmax, unsigned *outlen)
1063 {
1064 	if (!_cfmsasl_initted)
1065 		return SASL_NOMEM;
1066 	if (!saslcfmglob.prop_formatPtr) return SASL_NOMEM;
1067 
1068 	return saslcfmglob.prop_formatPtr(ctx, sep, seplen, outbuf, outmax, outlen);
1069 }
1070 
prop_set(struct propctx * ctx,const char * name,const char * value,int vallen)1071 int prop_set(struct propctx *ctx, const char *name,
1072 	     const char *value, int vallen)
1073 {
1074 	if (!_cfmsasl_initted)
1075 		return SASL_NOMEM;
1076 	if (!saslcfmglob.prop_setPtr) return SASL_NOMEM;
1077 
1078 	return saslcfmglob.prop_setPtr(ctx, name, value, vallen);
1079 }
1080 
prop_setvals(struct propctx * ctx,const char * name,const char ** values)1081 int prop_setvals(struct propctx *ctx, const char *name,
1082 		 const char **values)
1083 {
1084 	if (!_cfmsasl_initted)
1085 		return SASL_NOMEM;
1086 	if (!saslcfmglob.prop_setvalsPtr) return SASL_NOMEM;
1087 
1088 	return saslcfmglob.prop_setvalsPtr(ctx, name, values);
1089 }
1090 
1091 /* internal functions used by sasl_seterror follow */
_sasl_add_string(char ** out,int * alloclen,int * outlen,const char * add)1092 int _sasl_add_string(char **out, int *alloclen, int *outlen, const char *add)
1093 {
1094 	if (!_cfmsasl_initted)
1095 		return SASL_NOMEM;
1096 	if (!saslcfmglob._sasl_add_stringPtr) return SASL_NOMEM;
1097 
1098 	return saslcfmglob._sasl_add_stringPtr(out, alloclen, outlen, add);
1099 }
1100 
_buf_alloc(char ** rwbuf,unsigned * curlen,unsigned newlen)1101 int _buf_alloc(char **rwbuf, unsigned *curlen, unsigned newlen)
1102 {
1103 	if (!_cfmsasl_initted)
1104 		return SASL_NOMEM;
1105 	if (!saslcfmglob._buf_allocPtr) return SASL_NOMEM;
1106 
1107 	return saslcfmglob._buf_allocPtr(rwbuf, curlen, newlen);
1108 }
1109 
_sasl_get_errorbuf(sasl_conn_t * conn,char *** bufhdl,unsigned ** lenhdl)1110 void _sasl_get_errorbuf(sasl_conn_t *conn, char ***bufhdl, unsigned **lenhdl)
1111 {
1112 	if (!_cfmsasl_initted)
1113 		return;
1114 	if (!saslcfmglob._sasl_add_stringPtr) return;
1115 
1116 	saslcfmglob._sasl_get_errorbufPtr(((cfm_sasl_conn_t *)conn)->ctx, bufhdl, lenhdl);
1117 }
1118