/* cfmglue.c by Rolf Braun, for CMU SASL on Mac OS X This file provides routines to allow CFM (os 9 linkage) Carbon applications to use the native Mach-O SASL libraries on Mac OS X, using CFBundle to load the backend libraries and automatically allocated assembly callbacks $Id: cfmglue.c,v 1.4 2003/06/12 00:33:05 rbraun Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "Carnegie Mellon University" must not be used to * endorse or promote products derived from this software without * prior written permission. For permission or any other legal * details, please contact * Office of Technology Transfer * Carnegie Mellon University * 5000 Forbes Avenue * Pittsburgh, PA 15213-3890 * (412) 268-4387, fax: (412) 268-7395 * tech-transfer@andrew.cmu.edu * * 4. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Computing Services * at Carnegie Mellon University (http://www.cmu.edu/computing/)." * * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include "sasl.h" #include "saslutil.h" #include "prop.h" /* prototypes for internal functions (from saslint.h) */ int _sasl_add_string(char **out, int *alloclen, int *outlen, const char *add); int _buf_alloc(char **rwbuf, unsigned *curlen, unsigned newlen); void _sasl_get_errorbuf(sasl_conn_t *conn, char ***bufhdl, unsigned **lenhdl); void *MachOFunctionPointerForCFMFunctionPointer( void *cfmfp ); sasl_callback_t *GetCFMCallbacks(const sasl_callback_t *callbacks); void DisposeCFMCallbacks(sasl_callback_t *callbacks); int _cfmsasl_haveCustomAlloc = 0; int _cfmsasl_haveCustomMutex = 0; int _cfmsasl_initted = 0; /* DO NOT change the order of this struct! It MUST match that of the iovec struct in /usr/include/sys/uio.h on Mac OS X! It MUST also match that of the Mac OS 9 Carbon config.h since Carbon CFM stuff links at runtime against whatever it's running on! */ struct iovec { char *iov_base; long iov_len; }; typedef struct { CFURLRef bundleURL; CFBundleRef myBundle; sasl_callback_t *clientCallbacks; sasl_callback_t *serverCallbacks; int (*SASLClientNewPtr)(const char *service, const char *serverFQDN, const char *iplocalport, const char *ipremoteport, const sasl_callback_t *prompt_supp, unsigned flags, sasl_conn_t **pconn); int (*SASLClientStartPtr)(sasl_conn_t *conn, const char *mechlist, sasl_interact_t **prompt_need, const char **clientout, unsigned *clientoutlen, const char **mech); int (*SASLClientStepPtr)(sasl_conn_t *conn, const char *serverin, unsigned serverinlen, sasl_interact_t **prompt_need, const char **clientout, unsigned *clientoutlen); const char * (*SASLErrStringPtr)(int saslerr, const char *langlist, const char **outlang); const char *(*sasl_errdetailPtr)(sasl_conn_t *conn); int (*SASLGetPropPtr)(sasl_conn_t *conn, int propnum, const void **pvalue); int (*SASLSetPropPtr)(sasl_conn_t *conn, int propnum, const void *value); int (*SASLIdlePtr)(sasl_conn_t *conn); int (*SASLEncodePtr)(sasl_conn_t *conn, const char *input, unsigned inputlen, const char **output, unsigned *outputlen); int (*SASLDecodePtr)(sasl_conn_t *conn, const char *input, unsigned inputlen, const char **output, unsigned *outputlen); int (*SASLEncodeVPtr)(sasl_conn_t *conn, const struct iovec *invec, unsigned numiov, const char **output, unsigned *outputlen); int (*SASLDisposePtr)(sasl_conn_t **pconn); int (*SASLDonePtr)(); void (*SASLSetAllocPtr)(sasl_malloc_t *, sasl_calloc_t *, sasl_realloc_t *, sasl_free_t *); int (*sasl_decode64Ptr)(const char *in, unsigned inlen, char *out, unsigned outmax, unsigned *outlen); int (*sasl_encode64Ptr)(const char *in, unsigned inlen, char *out, unsigned outmax, unsigned *outlen); int (*sasl_mkchalPtr)(sasl_conn_t *conn, char *buf, unsigned maxlen, unsigned hostflag); int (*sasl_utf8verifyPtr)(const char *str, unsigned len); void (*sasl_churnPtr)(sasl_rand_t *rpool, const char *data, unsigned len); void (*sasl_randPtr)(sasl_rand_t *rpool, char *buf, unsigned len); void (*sasl_randseedPtr)(sasl_rand_t *rpool, const char *seed, unsigned len); void (*sasl_randfreePtr)(sasl_rand_t **rpool); int (*sasl_randcreatePtr)(sasl_rand_t **rpool); void (*SASLSetMutexPtr)(sasl_mutex_alloc_t *mn, sasl_mutex_lock_t *ml, sasl_mutex_unlock_t *mu, sasl_mutex_free_t *md); int (*SASLServerNewPtr)(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); int (*sasl_listmechPtr)(sasl_conn_t *conn, const char *user, const char *prefix, const char *sep, const char *suffix, const char **result, unsigned *plen, int *pcount); int (*SASLServerStartPtr)(sasl_conn_t *conn, const char *mech, const char *clientin, unsigned clientinlen, const char **serverout, unsigned *serveroutlen); int (*SASLServerStepPtr)(sasl_conn_t *conn, const char *clientin, unsigned clientinlen, const char **serverout, unsigned *serveroutlen); int (*sasl_checkpassPtr)(sasl_conn_t *conn, const char *user, unsigned userlen, const char *pass, unsigned passlen); int (*sasl_user_existsPtr)(sasl_conn_t *conn, const char *service, const char *user_realm, const char *user); int (*sasl_setpassPtr)(sasl_conn_t *conn, const char *user, const char *pass, unsigned passlen, const char *oldpass, unsigned oldpasslen, unsigned flags); int (*sasl_checkapopPtr)(sasl_conn_t *conn, const char *challenge, unsigned challen, const char *response, unsigned resplen); int (*sasl_auxprop_requestPtr)(sasl_conn_t *conn, const char **propnames); struct propctx *(*sasl_auxprop_getctxPtr)(sasl_conn_t *conn); void (*sasl_erasebufferPtr)(char *pass, unsigned len); struct propctx *(*prop_newPtr)(unsigned estimate); int (*prop_dupPtr)(struct propctx *src_ctx, struct propctx **dst_ctx); const struct propval *(*prop_getPtr)(struct propctx *ctx); int (*prop_getnamesPtr)(struct propctx *ctx, const char **names, struct propval *vals); void (*prop_clearPtr)(struct propctx *ctx, int requests); void (*prop_erasePtr)(struct propctx *ctx, const char *name); void (*prop_disposePtr)(struct propctx **ctx); int (*prop_formatPtr)(struct propctx *ctx, const char *sep, int seplen, char *outbuf, unsigned outmax, unsigned *outlen); int (*prop_setPtr)(struct propctx *ctx, const char *name, const char *value, int vallen); int (*prop_setvalsPtr)(struct propctx *ctx, const char *name, const char **values); int (*_sasl_add_stringPtr)(char **out, int *alloclen, int *outlen, const char *add); int (*_buf_allocPtr)(char **rwbuf, unsigned *curlen, unsigned newlen); void (*_sasl_get_errorbufPtr)(sasl_conn_t *conn, char ***bufhdl, unsigned **lenhdl); } GlobalsRec; typedef struct { sasl_malloc_t *custMalloc; sasl_calloc_t *custCalloc; sasl_realloc_t *custRealloc; sasl_free_t *custFree; sasl_mutex_alloc_t *custMutexNew; sasl_mutex_lock_t *custMutexLock; sasl_mutex_unlock_t *custMutexUnlock; sasl_mutex_free_t *custMutexDispose; } GlobalParamsRec; typedef struct { sasl_conn_t *ctx; sasl_callback_t *cbk; } cfm_sasl_conn_t; GlobalsRec saslcfmglob; // The globals GlobalParamsRec saslcfmglobp; // From Apple sample code... (CarbonLib SDK, CFM->MachO->CFM) // // This function allocates a block of CFM glue code which contains the instructions to call CFM routines // void *MachOFunctionPointerForCFMFunctionPointer( void *cfmfp ) { UInt32 template[6] = {0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420}; UInt32 *mfp = (UInt32*) NewPtr( sizeof(template) ); // Must later dispose of allocated memory mfp[0] = template[0] | ((UInt32)cfmfp >> 16); mfp[1] = template[1] | ((UInt32)cfmfp & 0xFFFF); mfp[2] = template[2]; mfp[3] = template[3]; mfp[4] = template[4]; mfp[5] = template[5]; MakeDataExecutable( mfp, sizeof(template) ); return( mfp ); } sasl_callback_t *GetCFMCallbacks(const sasl_callback_t *callbacks) { int cbksize = 0; const sasl_callback_t *cbk = callbacks; sasl_callback_t *ncbk, *new_callbacks; while (cbk->id) { cbksize++; cbk++; } cbksize++; cbk = callbacks; ncbk = new_callbacks = (sasl_callback_t *)NewPtr(cbksize * sizeof(sasl_callback_t)); if (!ncbk) return nil; while (cbksize--) { ncbk->id = cbk->id; ncbk->context = cbk->context; if (cbk->proc) ncbk->proc = MachOFunctionPointerForCFMFunctionPointer(cbk->proc); else ncbk->proc = nil; ncbk++; cbk++; } return new_callbacks; } void DisposeCFMCallbacks(sasl_callback_t *callbacks) { sasl_callback_t *cbk = callbacks; if (!cbk) return; while (cbk->id) { if (cbk->proc) DisposePtr((Ptr)cbk->proc); cbk++; } DisposePtr((Ptr)callbacks); } int _cfmsasl_common_init(const sasl_callback_t *callbacks, int isServer, const char *appname); int _cfmsasl_common_init(const sasl_callback_t *callbacks, int isServer, const char *appname) { int (*SASLClientInitPtr)(const sasl_callback_t *callbacks); int (*SASLServerInitPtr)(const sasl_callback_t *callbacks, const char *appname); int result = SASL_NOMEM; if (!_cfmsasl_initted) { // The skeleton for this code originally came from the CFM->MachO->CFM sample // provided by Aple with the Carbon SDK. It shows how to use CFBundle to call MachO // libraries from CFM and how to encapsulate callbacks into CFM. memset( &saslcfmglob, 0, sizeof(GlobalsRec) ); // Initialize the globals // Make a CFURLRef from the CFString representation of the bundle's path. // See the Core Foundation URL Services chapter for details. saslcfmglob.bundleURL = CFURLCreateWithFileSystemPath( nil, // workaround for Radar # 2452789 CFSTR("/Library/Frameworks/SASL2.framework"), // hard coded path for sample 0, true ); if ( saslcfmglob.bundleURL != NULL ) // Make a bundle instance using the URLRef. saslcfmglob.myBundle = CFBundleCreate( NULL /* kCFAllocatorDefault */, // workaround for Radar # 2452789 saslcfmglob.bundleURL ); if ( saslcfmglob.myBundle && CFBundleLoadExecutable( saslcfmglob.myBundle )) { // Try to load the executable from my bundle. // Now that the code is loaded, search for the functions we want by name. saslcfmglob.SASLClientNewPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_client_new") ); saslcfmglob.SASLClientStartPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_client_start") ); saslcfmglob.SASLClientStepPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_client_step") ); saslcfmglob.SASLErrStringPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_errstring") ); saslcfmglob.sasl_errdetailPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_errdetail") ); saslcfmglob.SASLGetPropPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_getprop") ); saslcfmglob.SASLSetPropPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_setprop") ); saslcfmglob.SASLIdlePtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_idle") ); saslcfmglob.SASLEncodePtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_encode") ); saslcfmglob.SASLEncodeVPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_encodev") ); saslcfmglob.SASLDecodePtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_decode") ); saslcfmglob.SASLDisposePtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_dispose") ); saslcfmglob.SASLDonePtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_done") ); saslcfmglob.SASLSetAllocPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_set_alloc") ); saslcfmglob.sasl_encode64Ptr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_encode64") ); saslcfmglob.sasl_decode64Ptr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_decode64") ); saslcfmglob.sasl_mkchalPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_mkchal") ); saslcfmglob.sasl_utf8verifyPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_utf8verify") ); saslcfmglob.sasl_churnPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_churn") ); saslcfmglob.sasl_randPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_rand") ); saslcfmglob.sasl_randseedPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_randseed") ); saslcfmglob.sasl_randcreatePtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_randcreate") ); saslcfmglob.sasl_randfreePtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_randfree") ); saslcfmglob.SASLSetMutexPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_set_mutex") ); saslcfmglob.SASLServerNewPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_server_new") ); saslcfmglob.SASLServerStartPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_server_start") ); saslcfmglob.SASLServerStepPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_server_step") ); saslcfmglob.sasl_listmechPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_listmech") ); saslcfmglob.sasl_checkpassPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_checkpass") ); saslcfmglob.sasl_setpassPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_setpass") ); saslcfmglob.sasl_user_existsPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_user_exists") ); saslcfmglob.sasl_checkapopPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_checkapop") ); saslcfmglob.sasl_auxprop_requestPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_auxprop_request") ); saslcfmglob.sasl_auxprop_getctxPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_auxprop_getctx") ); saslcfmglob.sasl_erasebufferPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_erasebuffer") ); saslcfmglob.prop_newPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("prop_new") ); saslcfmglob.prop_dupPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("prop_dup") ); saslcfmglob.prop_getPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("prop_get") ); saslcfmglob.prop_getnamesPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("prop_getnames") ); saslcfmglob.prop_clearPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("prop_clear") ); saslcfmglob.prop_erasePtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("prop_erase") ); saslcfmglob.prop_disposePtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("prop_dispose") ); saslcfmglob.prop_formatPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("prop_format") ); saslcfmglob.prop_setPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("prop_set") ); saslcfmglob.prop_setvalsPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("prop_setvals") ); /* These are internal functions used by our sasl_seterror */ saslcfmglob._sasl_add_stringPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("_sasl_add_string") ); saslcfmglob._buf_allocPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("_buf_alloc") ); saslcfmglob._sasl_get_errorbufPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("_sasl_get_errorbuf") ); if (!_cfmsasl_haveCustomAlloc) { saslcfmglobp.custMalloc = MachOFunctionPointerForCFMFunctionPointer(malloc); saslcfmglobp.custCalloc = MachOFunctionPointerForCFMFunctionPointer(calloc); saslcfmglobp.custRealloc = MachOFunctionPointerForCFMFunctionPointer(realloc); saslcfmglobp.custFree = MachOFunctionPointerForCFMFunctionPointer(free); _cfmsasl_haveCustomAlloc = 1; } saslcfmglob.SASLSetAllocPtr(saslcfmglobp.custMalloc, saslcfmglobp.custCalloc, saslcfmglobp.custRealloc, saslcfmglobp.custFree); if (_cfmsasl_haveCustomMutex) saslcfmglob.SASLSetMutexPtr(saslcfmglobp.custMutexNew, saslcfmglobp.custMutexLock, saslcfmglobp.custMutexUnlock, saslcfmglobp.custMutexDispose); } else if (saslcfmglob.myBundle) { CFRelease(saslcfmglob.myBundle); saslcfmglob.myBundle = nil; } if (saslcfmglob.bundleURL && !saslcfmglob.myBundle) { CFRelease(saslcfmglob.bundleURL); saslcfmglob.bundleURL = nil; } if (saslcfmglob.myBundle) _cfmsasl_initted = 1; } if (_cfmsasl_initted) { if (isServer) { SASLServerInitPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_server_init") ); if (SASLServerInitPtr != nil) { sasl_callback_t *new_callbacks = NULL; if (callbacks) new_callbacks = GetCFMCallbacks(callbacks); result = SASLServerInitPtr(new_callbacks, appname); saslcfmglob.serverCallbacks = new_callbacks; } } else { SASLClientInitPtr = (void*)CFBundleGetFunctionPointerForName( saslcfmglob.myBundle, CFSTR("sasl_client_init") ); if (SASLClientInitPtr != nil) { sasl_callback_t *new_callbacks = NULL; if (callbacks) new_callbacks = GetCFMCallbacks(callbacks); result = SASLClientInitPtr(new_callbacks); saslcfmglob.clientCallbacks = new_callbacks; } } } return result; } int sasl_server_init(const sasl_callback_t *callbacks, const char *appname) { return _cfmsasl_common_init(callbacks, true, appname); } int sasl_client_init(const sasl_callback_t *callbacks) { return _cfmsasl_common_init(callbacks, false, nil); } void sasl_done(void) { if (!_cfmsasl_initted) return; if (!saslcfmglob.SASLDonePtr) return; saslcfmglob.SASLDonePtr(); DisposeCFMCallbacks(saslcfmglob.clientCallbacks); DisposeCFMCallbacks(saslcfmglob.serverCallbacks); CFBundleUnloadExecutable(saslcfmglob.myBundle); CFRelease(saslcfmglob.myBundle); CFRelease(saslcfmglob.bundleURL); saslcfmglob.myBundle = NULL; saslcfmglob.bundleURL = NULL; _cfmsasl_initted = 0; } int 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) { sasl_callback_t *new_ps = NULL; int result; cfm_sasl_conn_t *myconn; if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLClientNewPtr) return SASL_NOMEM; if (prompt_supp) new_ps = GetCFMCallbacks(prompt_supp); // this is commented out because sasl.h incorrectly described the api // if (*pconn) // DisposeCFMCallbacks(((cfm_sasl_conn_t *)*pconn)->cbk); // else { myconn = (cfm_sasl_conn_t *) NewPtr(sizeof(cfm_sasl_conn_t)); if (myconn == NULL) { return SASL_NOMEM; } myconn->ctx = NULL; // } result = saslcfmglob.SASLClientNewPtr(service, serverFQDN, iplocalport, ipremoteport, new_ps, flags, &(myconn->ctx)); myconn->cbk = new_ps; *pconn = (sasl_conn_t *)myconn; return result; } int 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) { sasl_callback_t *new_ps = NULL; int result; if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLServerNewPtr) return SASL_NOMEM; if (callbacks) new_ps = GetCFMCallbacks(callbacks); *pconn = (sasl_conn_t *)NewPtr(sizeof(cfm_sasl_conn_t)); ((cfm_sasl_conn_t *)*pconn)->ctx = nil; result = saslcfmglob.SASLServerNewPtr(service, serverFQDN, user_realm, iplocalport, ipremoteport, new_ps, flags, &((cfm_sasl_conn_t *)*pconn)->ctx); ((cfm_sasl_conn_t *)*pconn)->cbk = new_ps; return result; } void sasl_dispose(sasl_conn_t **pconn) { if (!_cfmsasl_initted) return; if (!saslcfmglob.SASLDisposePtr) return; if (!pconn) return; if (!*pconn) return; saslcfmglob.SASLDisposePtr(&((cfm_sasl_conn_t *)*pconn)->ctx); DisposeCFMCallbacks(((cfm_sasl_conn_t *)*pconn)->cbk); DisposePtr((Ptr)*pconn); *pconn = NULL; } int sasl_client_start (sasl_conn_t *conn, const char *mechlist, sasl_interact_t **prompt_need, const char **clientout, unsigned *clientoutlen, const char **mech) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLClientStartPtr) return SASL_NOMEM; return saslcfmglob.SASLClientStartPtr(((cfm_sasl_conn_t *)conn)->ctx, mechlist, prompt_need, clientout, clientoutlen, mech); } int sasl_client_step (sasl_conn_t *conn, const char *serverin, unsigned serverinlen, sasl_interact_t **prompt_need, const char **clientout, unsigned *clientoutlen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLClientStepPtr) return SASL_NOMEM; return saslcfmglob.SASLClientStepPtr(((cfm_sasl_conn_t *)conn)->ctx, serverin, serverinlen, prompt_need, clientout, clientoutlen); } const char *sasl_errstring(int saslerr, const char *langlist, const char **outlang) { if (!_cfmsasl_initted) return NULL; if (!saslcfmglob.SASLErrStringPtr) return NULL; return saslcfmglob.SASLErrStringPtr(saslerr, langlist, outlang); } const char *sasl_errdetail(sasl_conn_t *conn) { if (!_cfmsasl_initted) return NULL; if (!saslcfmglob.sasl_errdetailPtr) return NULL; return saslcfmglob.sasl_errdetailPtr(((cfm_sasl_conn_t *)conn)->ctx); } int sasl_getprop(sasl_conn_t *conn, int propnum, const void **pvalue) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLGetPropPtr) return SASL_NOMEM; return saslcfmglob.SASLGetPropPtr(((cfm_sasl_conn_t *)conn)->ctx, propnum, pvalue); } int sasl_setprop(sasl_conn_t *conn, int propnum, const void *value) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLSetPropPtr) return SASL_NOMEM; return saslcfmglob.SASLSetPropPtr(((cfm_sasl_conn_t *)conn)->ctx, propnum, value); } int sasl_idle(sasl_conn_t *conn) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLIdlePtr) return SASL_NOMEM; return saslcfmglob.SASLIdlePtr(((cfm_sasl_conn_t *)conn)->ctx); } int sasl_encode(sasl_conn_t *conn, const char *input, unsigned inputlen, const char **output, unsigned *outputlen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLEncodePtr) return SASL_NOMEM; return saslcfmglob.SASLEncodePtr(((cfm_sasl_conn_t *)conn)->ctx, input, inputlen, output, outputlen); } int sasl_encodev(sasl_conn_t *conn, const struct iovec *invec, unsigned numiov, const char **output, unsigned *outputlen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLEncodeVPtr) return SASL_NOMEM; return saslcfmglob.SASLEncodeVPtr(((cfm_sasl_conn_t *)conn)->ctx, invec, numiov, output, outputlen); } int sasl_decode(sasl_conn_t *conn, const char *input, unsigned inputlen, const char **output, unsigned *outputlen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLDecodePtr) return SASL_NOMEM; return saslcfmglob.SASLDecodePtr(((cfm_sasl_conn_t *)conn)->ctx, input, inputlen, output, outputlen); } int sasl_decode64(const char *in, unsigned inlen, char *out, unsigned outmax, unsigned *outlen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.sasl_decode64Ptr) return SASL_NOMEM; return saslcfmglob.sasl_decode64Ptr(in, inlen, out, outmax, outlen); } int sasl_encode64(const char *in, unsigned inlen, char *out, unsigned outmax, unsigned *outlen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.sasl_encode64Ptr) return SASL_NOMEM; return saslcfmglob.sasl_encode64Ptr(in, inlen, out, outmax, outlen); } void sasl_set_alloc(sasl_malloc_t *ma, sasl_calloc_t *ca, sasl_realloc_t *rea, sasl_free_t *fr) { if (_cfmsasl_haveCustomAlloc) { DisposePtr((Ptr)saslcfmglobp.custMalloc); DisposePtr((Ptr)saslcfmglobp.custCalloc); DisposePtr((Ptr)saslcfmglobp.custRealloc); DisposePtr((Ptr)saslcfmglobp.custFree); } saslcfmglobp.custMalloc = MachOFunctionPointerForCFMFunctionPointer(ma); saslcfmglobp.custCalloc = MachOFunctionPointerForCFMFunctionPointer(ca); saslcfmglobp.custRealloc = MachOFunctionPointerForCFMFunctionPointer(rea); saslcfmglobp.custFree = MachOFunctionPointerForCFMFunctionPointer(fr); _cfmsasl_haveCustomAlloc = 1; } int sasl_mkchal(sasl_conn_t *conn, char *buf, unsigned maxlen, unsigned hostflag) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.sasl_mkchalPtr) return SASL_NOMEM; return saslcfmglob.sasl_mkchalPtr(((cfm_sasl_conn_t *)conn)->ctx, buf, maxlen, hostflag); } int sasl_utf8verify(const char *str, unsigned len) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.sasl_utf8verifyPtr) return SASL_NOMEM; return saslcfmglob.sasl_utf8verifyPtr(str, len); } void sasl_churn(sasl_rand_t *rpool, const char *data, unsigned len) { if (!_cfmsasl_initted) return; if (!saslcfmglob.sasl_churnPtr) return; saslcfmglob.sasl_churnPtr(rpool, data, len); } void sasl_rand(sasl_rand_t *rpool, char *buf, unsigned len) { if (!_cfmsasl_initted) return; if (!saslcfmglob.sasl_randPtr) return; saslcfmglob.sasl_randPtr(rpool, buf, len); } void sasl_randseed(sasl_rand_t *rpool, const char *seed, unsigned len) { if (!_cfmsasl_initted) return; if (!saslcfmglob.sasl_randseedPtr) return; saslcfmglob.sasl_randseedPtr(rpool, seed, len); } void sasl_randfree(sasl_rand_t **rpool) { if (!_cfmsasl_initted) return; if (!saslcfmglob.sasl_randfreePtr) return; saslcfmglob.sasl_randfreePtr(rpool); } int sasl_randcreate(sasl_rand_t **rpool) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.sasl_randcreatePtr) return SASL_NOMEM; return saslcfmglob.sasl_randcreatePtr(rpool); } void sasl_set_mutex(sasl_mutex_alloc_t *mn, sasl_mutex_lock_t *ml, sasl_mutex_unlock_t *mu, sasl_mutex_free_t *md) { if (_cfmsasl_haveCustomMutex) { DisposePtr((Ptr)saslcfmglobp.custMutexNew); DisposePtr((Ptr)saslcfmglobp.custMutexLock); DisposePtr((Ptr)saslcfmglobp.custMutexUnlock); DisposePtr((Ptr)saslcfmglobp.custMutexDispose); } saslcfmglobp.custMutexNew = MachOFunctionPointerForCFMFunctionPointer(mn); saslcfmglobp.custMutexLock = MachOFunctionPointerForCFMFunctionPointer(ml); saslcfmglobp.custMutexUnlock = MachOFunctionPointerForCFMFunctionPointer(mu); saslcfmglobp.custMutexDispose = MachOFunctionPointerForCFMFunctionPointer(md); _cfmsasl_haveCustomMutex = 1; } int 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) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.sasl_listmechPtr) return SASL_NOMEM; return saslcfmglob.sasl_listmechPtr(((cfm_sasl_conn_t *)conn)->ctx, user, prefix, sep, suffix, result, plen, pcount); } int sasl_server_start(sasl_conn_t *conn, const char *mech, const char *clientin, unsigned clientinlen, const char **serverout, unsigned *serveroutlen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLServerStartPtr) return SASL_NOMEM; return saslcfmglob.SASLServerStartPtr(((cfm_sasl_conn_t *)conn)->ctx, mech, clientin, clientinlen, serverout, serveroutlen); } int sasl_server_step(sasl_conn_t *conn, const char *clientin, unsigned clientinlen, const char **serverout, unsigned *serveroutlen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.SASLServerStepPtr) return SASL_NOMEM; return saslcfmglob.SASLServerStepPtr(((cfm_sasl_conn_t *)conn)->ctx, clientin, clientinlen, serverout, serveroutlen); } int sasl_checkpass(sasl_conn_t *conn, const char *user, unsigned userlen, const char *pass, unsigned passlen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.sasl_checkpassPtr) return SASL_NOMEM; return saslcfmglob.sasl_checkpassPtr(((cfm_sasl_conn_t *)conn)->ctx, user, userlen, pass, passlen); } int sasl_user_exists(sasl_conn_t *conn, const char *service, const char *user_realm, const char *user) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.sasl_user_existsPtr) return SASL_NOMEM; return saslcfmglob.sasl_user_existsPtr(((cfm_sasl_conn_t *)conn)->ctx, service, user_realm, user); } int sasl_setpass(sasl_conn_t *conn, const char *user, const char *pass, unsigned passlen, const char *oldpass, unsigned oldpasslen, unsigned flags) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.sasl_setpassPtr) return SASL_NOMEM; return saslcfmglob.sasl_setpassPtr(((cfm_sasl_conn_t *)conn)->ctx, user, pass, passlen, oldpass, oldpasslen, flags); } int sasl_checkapop(sasl_conn_t *conn, const char *challenge, unsigned challen, const char *response, unsigned resplen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.sasl_checkapopPtr) return SASL_NOMEM; return saslcfmglob.sasl_checkapopPtr(((cfm_sasl_conn_t *)conn)->ctx, challenge, challen, response, resplen); } int sasl_auxprop_request(sasl_conn_t *conn, const char **propnames) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.sasl_auxprop_requestPtr) return SASL_NOMEM; return saslcfmglob.sasl_auxprop_requestPtr(((cfm_sasl_conn_t *)conn)->ctx, propnames); } struct propctx *sasl_auxprop_getctx(sasl_conn_t *conn) { if (!_cfmsasl_initted) return NULL; if (!saslcfmglob.sasl_auxprop_getctxPtr) return NULL; return saslcfmglob.sasl_auxprop_getctxPtr(((cfm_sasl_conn_t *)conn)->ctx); } void sasl_erasebuffer(char *pass, unsigned len) { if (!_cfmsasl_initted) return; if (!saslcfmglob.sasl_erasebufferPtr) return; saslcfmglob.sasl_erasebufferPtr(pass, len); } struct propctx *prop_new(unsigned estimate) { if (!_cfmsasl_initted) return NULL; if (!saslcfmglob.prop_newPtr) return NULL; return saslcfmglob.prop_newPtr(estimate); } int prop_dup(struct propctx *src_ctx, struct propctx **dst_ctx) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.prop_dupPtr) return SASL_NOMEM; return saslcfmglob.prop_dupPtr(src_ctx, dst_ctx); } const struct propval *prop_get(struct propctx *ctx) { if (!_cfmsasl_initted) return NULL; if (!saslcfmglob.prop_getPtr) return NULL; return saslcfmglob.prop_getPtr(ctx); } int prop_getnames(struct propctx *ctx, const char **names, struct propval *vals) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.prop_getnamesPtr) return SASL_NOMEM; return saslcfmglob.prop_getnamesPtr(ctx, names, vals); } void prop_clear(struct propctx *ctx, int requests) { if (!_cfmsasl_initted) return; if (!saslcfmglob.prop_clearPtr) return; saslcfmglob.prop_clearPtr(ctx, requests); } void prop_erase(struct propctx *ctx, const char *name) { if (!_cfmsasl_initted) return; if (!saslcfmglob.prop_erasePtr) return; saslcfmglob.prop_erasePtr(ctx, name); } void prop_dispose(struct propctx **ctx) { if (!_cfmsasl_initted) return; if (!saslcfmglob.prop_disposePtr) return; saslcfmglob.prop_disposePtr(ctx); } int prop_format(struct propctx *ctx, const char *sep, int seplen, char *outbuf, unsigned outmax, unsigned *outlen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.prop_formatPtr) return SASL_NOMEM; return saslcfmglob.prop_formatPtr(ctx, sep, seplen, outbuf, outmax, outlen); } int prop_set(struct propctx *ctx, const char *name, const char *value, int vallen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.prop_setPtr) return SASL_NOMEM; return saslcfmglob.prop_setPtr(ctx, name, value, vallen); } int prop_setvals(struct propctx *ctx, const char *name, const char **values) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob.prop_setvalsPtr) return SASL_NOMEM; return saslcfmglob.prop_setvalsPtr(ctx, name, values); } /* internal functions used by sasl_seterror follow */ int _sasl_add_string(char **out, int *alloclen, int *outlen, const char *add) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob._sasl_add_stringPtr) return SASL_NOMEM; return saslcfmglob._sasl_add_stringPtr(out, alloclen, outlen, add); } int _buf_alloc(char **rwbuf, unsigned *curlen, unsigned newlen) { if (!_cfmsasl_initted) return SASL_NOMEM; if (!saslcfmglob._buf_allocPtr) return SASL_NOMEM; return saslcfmglob._buf_allocPtr(rwbuf, curlen, newlen); } void _sasl_get_errorbuf(sasl_conn_t *conn, char ***bufhdl, unsigned **lenhdl) { if (!_cfmsasl_initted) return; if (!saslcfmglob._sasl_add_stringPtr) return; saslcfmglob._sasl_get_errorbufPtr(((cfm_sasl_conn_t *)conn)->ctx, bufhdl, lenhdl); }