diff --git a/Users/smichaud/Documents/ReverseEngineering/HookCase-master/HookLibraryTemplate/hook.mm b/hook.mm index e7102fb..d7e0fce 100644 --- a/Users/smichaud/Documents/ReverseEngineering/HookCase-master/HookLibraryTemplate/hook.mm +++ b/hook.mm @@ -1019,6 +1019,8 @@ loadHandler::loadHandler() LogWithFormat(true, "Hook.mm: loadHandler()"); PrintStackTrace(); #endif + + LogWithFormat(true, "Hook.mm: loadHandler()"); } loadHandler::~loadHandler() @@ -1200,6 +1202,748 @@ static int Hooked_interpose_example(char *arg1, int (*arg2)(char *)) // Put other hooked methods and swizzled classes here +typedef signed char INT1; /* 8 bits */ +typedef short INT2; /* 16 bits */ +typedef int INT4; /* 32 bits */ +/* There is no 64 bit type */ +typedef unsigned char UINT1; /* 8 bits */ +typedef unsigned short UINT2; /* 16 bits */ +typedef unsigned int UINT4; /* 32 bits */ +/* There is no 64 bit type */ + +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +#define CANON_BUF_SIZE 1024 + +enum Sasl_conn_type { SASL_CONN_UNKNOWN = 0, + SASL_CONN_SERVER = 1, + SASL_CONN_CLIENT = 2 }; + +/* security layer strength factor -- an unsigned integer usable by the caller + * to specify approximate security layer strength desired. Roughly + * correlated to effective key length for encryption. + * 0 = no protection + * 1 = integrity protection only + * 40 = 40-bit DES or 40-bit RC2/RC4 + * 56 = DES + * 112 = triple-DES + * 128 = 128-bit RC2/RC4/BLOWFISH + * 256 = baseline AES + */ +typedef unsigned sasl_ssf_t; + +#define SASL_CB_LIST_END 0 /* end of list */ +#define SASL_CB_GETOPT 1 +#define SASL_CB_LOG 2 +#define SASL_CB_GETPATH 3 +#define SASL_CB_VERIFYFILE 4 +#define SASL_CB_GETCONFPATH 5 +#define SASL_CB_USER 0x4001 /* client user identity to login as */ +#define SASL_CB_AUTHNAME 0x4002 /* client authentication name */ +#define SASL_CB_LANGUAGE 0x4003 /* comma separated list of RFC 1766 + * language codes in order of preference + * to be used to localize client prompts + * or server error codes */ +#define SASL_CB_CNONCE 0x4007 /* caller supplies client-nonce + * primarily for testing purposes */ +#define SASL_CB_PASS 0x4004 /* client passphrase-based secret */ +#define SASL_CB_ECHOPROMPT 0x4005 /* challenge and client enterred result */ +#define SASL_CB_NOECHOPROMPT 0x4006 /* challenge and client enterred result */ +#define SASL_CB_GETREALM (0x4008) /* realm to attempt authentication in */ +#define SASL_CB_PROXY_POLICY 0x8001 +#define SASL_CB_SERVER_USERDB_CHECKPASS (0x8005) +#define SASL_CB_SERVER_USERDB_SETPASS (0x8006) +#define SASL_CB_CANON_USER (0x8007) + +typedef struct buffer_info { + char *data; + size_t curlen; + size_t reallen; +} buffer_info_t; + +typedef struct sasl_callback { + /* Identifies the type of the callback function. + * Mechanisms must ignore callbacks with id's they don't recognize. + */ + unsigned long id; + int (*proc)(void); /* Callback function. Types of arguments vary by 'id' */ + void *context; +} sasl_callback_t; + +typedef struct { + const sasl_callback_t *callbacks; + const char *appname; +} sasl_global_callbacks_t; + +typedef struct sasl_out_params { + unsigned doneflag; /* exchange complete */ + + const char *user; /* canonicalized user name */ + const char *authid; /* canonicalized authentication id */ + + unsigned ulen; /* length of canonicalized user name */ + unsigned alen; /* length of canonicalized authid */ + + /* security layer information */ + unsigned maxoutbuf; /* Maximum buffer size, which will + produce buffer no bigger than the + negotiated SASL maximum buffer size */ + sasl_ssf_t mech_ssf; /* Should be set non-zero if negotiation of a + * security layer was *attempted*, even if + * the negotiation failed */ + void *encode_context; + int (*encode)(void *context, const struct iovec *invec, unsigned numiov, + const char **output, unsigned *outputlen); + void *decode_context; + int (*decode)(void *context, const char *input, unsigned inputlen, + const char **output, unsigned *outputlen); + + /* Pointer to delegated (client's) credentials, if supported by + the SASL mechanism */ + void *client_creds; + + /* for additions which don't require a version upgrade; set to 0 */ + const void *gss_peer_name; + const void *gss_local_name; + const char *cbindingname; /* channel binding name from packet */ + int (*spare_fptr1)(void); + int (*spare_fptr2)(void); + unsigned int cbindingdisp; /* channel binding disposition from client */ + int spare_int2; + int spare_int3; + int spare_int4; + + /* set to 0 initially, this allows a plugin with extended parameters + * to work with an older framework by updating version as parameters + * are added. + */ + int param_version; +} sasl_out_params_t; + +typedef struct _sasl_external_properties { + sasl_ssf_t ssf; + char *auth_id; +} _sasl_external_properties_t; + +typedef struct sasl_security_properties { + /* security strength factor + * min_ssf = minimum acceptable final level + * max_ssf = maximum acceptable final level + */ + sasl_ssf_t min_ssf; + sasl_ssf_t max_ssf; + + /* Maximum security layer receive buffer size. + * 0=security layer not supported + */ + unsigned maxbufsize; + + /* bitfield for attacks to protect against */ + unsigned security_flags; + + /* NULL terminated array of additional property names, values */ + const char **property_names; + const char **property_values; +} sasl_security_properties_t; + +typedef struct sasl_secret { + unsigned long len; + unsigned char data[1]; /* variable sized */ +} sasl_secret_t; + +typedef struct sasl_conn sasl_conn_t; + +struct sasl_conn { + enum Sasl_conn_type type; + + void (*destroy_conn)(sasl_conn_t *); /* destroy function */ + + char *service; + + unsigned int flags; /* flags passed to sasl_*_new */ + + /* IP information. A buffer of size 52 is adequate for this in its + longest format (see sasl.h) */ + int got_ip_local, got_ip_remote; + char iplocalport[NI_MAXHOST + NI_MAXSERV]; + char ipremoteport[NI_MAXHOST + NI_MAXSERV]; + + void *context; + sasl_out_params_t oparams; + + sasl_security_properties_t props; + _sasl_external_properties_t external; + + sasl_secret_t *secret; + + int (*idle_hook)(sasl_conn_t *conn); + const sasl_callback_t *callbacks; + const sasl_global_callbacks_t *global_callbacks; /* global callbacks + * connection */ + char *serverFQDN; + + /* Pointers to memory that we are responsible for */ + buffer_info_t *encode_buf; + + int error_code; + char *error_buf, *errdetail_buf; + size_t error_buf_len, errdetail_buf_len; + char *mechlist_buf; + size_t mechlist_buf_len; + + char *decode_buf; + + char user_buf[CANON_BUF_SIZE+1], authid_buf[CANON_BUF_SIZE+1]; + + /* Allocated by sasl_encodev if the output contains multiple SASL packet. */ + buffer_info_t multipacket_encoded_data; +}; + +typedef struct sasl_rand_s sasl_rand_t; + +typedef int sasl_getopt_t(void *context, const char *plugin_name, + const char *option, + const char **result, unsigned *len); + +typedef void *sasl_malloc_t(size_t); +typedef void *sasl_calloc_t(size_t, size_t); +typedef void *sasl_realloc_t(void *, size_t); +typedef void sasl_free_t(void *); + +typedef void *sasl_mutex_alloc_t(void); +typedef int sasl_mutex_lock_t(void *mutex); +typedef int sasl_mutex_unlock_t(void *mutex); +typedef void sasl_mutex_free_t(void *mutex); + +/* MD5 context. */ +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +typedef struct HMAC_MD5_CTX_s { + MD5_CTX ictx, octx; +} HMAC_MD5_CTX; + +typedef struct HMAC_MD5_STATE_s { + UINT4 istate[4]; + UINT4 ostate[4]; +} HMAC_MD5_STATE; + +typedef int (*sasl_callback_ft)(void); +typedef int sasl_getcallback_t(sasl_conn_t *conn, + unsigned long callbackid, + sasl_callback_ft * pproc, + void **pcontext); + +struct propctx; + +struct propval { + const char *name; /* name of property; NULL = end of list */ + /* same pointer used in request will be used here */ + const char **values; /* list of strings, values == NULL if property not + * found, *values == NULL if property found with + * no values */ + unsigned nvalues; /* total number of value strings */ + unsigned valsize; /* total size in characters of all value strings */ +}; + +typedef struct sasl_utils { + int version; + + /* contexts */ + sasl_conn_t *conn; + sasl_rand_t *rpool; + void *getopt_context; + + /* option function */ + sasl_getopt_t *getopt; + + /* allocation functions: */ + sasl_malloc_t *malloc; + sasl_calloc_t *calloc; + sasl_realloc_t *realloc; + sasl_free_t *free; + + /* mutex functions: */ + sasl_mutex_alloc_t *mutex_alloc; + sasl_mutex_lock_t *mutex_lock; + sasl_mutex_unlock_t *mutex_unlock; + sasl_mutex_free_t *mutex_free; + + /* MD5 hash and HMAC functions */ + void (*MD5Init)(MD5_CTX *); + void (*MD5Update)(MD5_CTX *, const unsigned char *text, unsigned int len); + void (*MD5Final)(unsigned char [16], MD5_CTX *); + void (*hmac_md5)(const unsigned char *text, int text_len, + const unsigned char *key, int key_len, + unsigned char [16]); + void (*hmac_md5_init)(HMAC_MD5_CTX *, const unsigned char *key, int len); + /* hmac_md5_update() is just a call to MD5Update on inner context */ + void (*hmac_md5_final)(unsigned char [16], HMAC_MD5_CTX *); + void (*hmac_md5_precalc)(HMAC_MD5_STATE *, + const unsigned char *key, int len); + void (*hmac_md5_import)(HMAC_MD5_CTX *, HMAC_MD5_STATE *); + + /* mechanism utility functions (same as above): */ + int (*mkchal)(sasl_conn_t *conn, char *buf, unsigned maxlen, + unsigned hostflag); + int (*utf8verify)(const char *str, unsigned len); + void (*rand)(sasl_rand_t *rpool, char *buf, unsigned len); + void (*churn)(sasl_rand_t *rpool, const char *data, unsigned len); + + /* This allows recursive calls to the sasl_checkpass() routine from + * within a SASL plug-in. This MUST NOT be used in the PLAIN mechanism + * as sasl_checkpass MAY be a front-end for the PLAIN mechanism. + * This is intended for use by the non-standard LOGIN mechanism and + * potentially by a future mechanism which uses public-key technology to + * set up a lightweight encryption layer just for sending a password. + */ + int (*checkpass)(sasl_conn_t *conn, + const char *user, unsigned userlen, + const char *pass, unsigned passlen); + + /* Access to base64 encode/decode routines */ + int (*decode64)(const char *in, unsigned inlen, + char *out, unsigned outmax, unsigned *outlen); + int (*encode64)(const char *in, unsigned inlen, + char *out, unsigned outmax, unsigned *outlen); + + /* erase a buffer */ + void (*erasebuffer)(char *buf, unsigned len); + + /* callback to sasl_getprop() and sasl_setprop() */ + int (*getprop)(sasl_conn_t *conn, int propnum, const void **pvalue); + int (*setprop)(sasl_conn_t *conn, int propnum, const void *value); + + /* callback function */ + sasl_getcallback_t *getcallback; + + /* format a message and then pass it to the SASL_CB_LOG callback + * + * use syslog()-style formatting (printf with %m as a human readable text + * (strerror()) for the error specified as the parameter). + * The implementation may use a fixed size buffer not smaller + * than 512 octets if it securely truncates the message. + * + * level is a SASL_LOG_* level (see sasl.h) + */ + void (*log)(sasl_conn_t *conn, int level, const char *fmt, ...) __attribute__((format(printf, 3, 4))); + + /* callback to sasl_seterror() */ + void (*seterror)(sasl_conn_t *conn, unsigned flags, const char *fmt, ...) __attribute__((format(printf, 3, 4))); + + /* spare function pointer */ + int *(*spare_fptr)(void); + + /* auxiliary property utilities */ + struct propctx *(*prop_new)(unsigned estimate); + int (*prop_dup)(struct propctx *src_ctx, struct propctx **dst_ctx); + int (*prop_request)(struct propctx *ctx, const char **names); + const struct propval *(*prop_get)(struct propctx *ctx); + int (*prop_getnames)(struct propctx *ctx, const char **names, + struct propval *vals); + void (*prop_clear)(struct propctx *ctx, int requests); + void (*prop_dispose)(struct propctx **ctx); + int (*prop_format)(struct propctx *ctx, const char *sep, int seplen, + char *outbuf, unsigned outmax, unsigned *outlen); + int (*prop_set)(struct propctx *ctx, const char *name, + const char *value, int vallen); + int (*prop_setvals)(struct propctx *ctx, const char *name, + const char **values); + void (*prop_erase)(struct propctx *ctx, const char *name); + int (*auxprop_store)(sasl_conn_t *conn, + struct propctx *ctx, const char *user); + + /* for additions which don't require a version upgrade; set to 0 */ + int (*spare_fptr1)(void); + int (*spare_fptr2)(void); +} sasl_utils_t; + +typedef struct sasl_channel_binding { + const char *name; + int critical; + unsigned long len; + const unsigned char *data; +} sasl_channel_binding_t; + +typedef struct sasl_http_request { + const char *method; /* HTTP Method */ + const char *uri; /* request-URI */ + const unsigned char *entity; /* entity-body */ + unsigned long elen; /* entity-body length */ + unsigned non_persist; /* Is it a non-persistent connection? */ +} sasl_http_request_t; + +typedef struct sasl_client_params { + const char *service; /* service name */ + const char *serverFQDN; /* server fully qualified domain name */ + const char *clientFQDN; /* client's fully qualified domain name */ + const sasl_utils_t *utils; /* SASL API utility routines -- + * for a particular sasl_conn_t, + * MUST remain valid until mech_free is + * called */ + const sasl_callback_t *prompt_supp; /* client callback list */ + const char *iplocalport; /* server IP domain literal & port */ + const char *ipremoteport; /* client IP domain literal & port */ + + unsigned servicelen; /* length of service */ + unsigned slen; /* length of serverFQDN */ + unsigned clen; /* length of clientFQDN */ + unsigned iploclen; /* length of iplocalport */ + unsigned ipremlen; /* length of ipremoteport */ + + /* application's security requirements & info */ + sasl_security_properties_t props; + sasl_ssf_t external_ssf; /* external SSF active */ + + /* for additions which don't require a version upgrade; set to 0 */ + const void *gss_creds; /* GSS credential handle */ + const sasl_channel_binding_t *cbinding; /* client channel binding */ + const sasl_http_request_t *http_request;/* HTTP Digest request method */ + void *spare_ptr4; + + /* Canonicalize a user name from on-wire to internal format + * added rjs3 2001-05-23 + * Must be called once user name aquired if canon_user is non-NULL. + * conn connection context + * in user name from wire protocol (need not be NUL terminated) + * len length of user name from wire protocol (0 = strlen(user)) + * flags for SASL_CU_* flags + * oparams the user, authid, ulen, alen, fields are + * set appropriately after canonicalization/copying and + * authorization of arguments + * + * responsible for setting user, ulen, authid, and alen in the oparams + * structure + * + * default behavior is to strip leading and trailing whitespace, as + * well as allocating space for and copying the parameters. + * + * results: + * SASL_OK -- success + * SASL_NOMEM -- out of memory + * SASL_BADPARAM -- invalid conn + * SASL_BADPROT -- invalid user/authid + */ + int (*canon_user)(sasl_conn_t *conn, + const char *in, unsigned len, + unsigned flags, + sasl_out_params_t *oparams); + + int (*spare_fptr1)(void); + + unsigned int cbindingdisp; + int spare_int2; + int spare_int3; + + /* flags field as passed to sasl_client_new */ + unsigned flags; + + /* set to 0 initially, this allows a plugin with extended parameters + * to work with an older framework by updating version as parameters + * are added. + */ + int param_version; +} sasl_client_params_t; + +typedef struct sasl_interact { + unsigned long id; /* same as client/user callback ID */ + const char *challenge; /* presented to user (e.g. OTP challenge) */ + const char *prompt; /* presented to user (e.g. "Username: ") */ + const char *defresult; /* default result string */ + const void *result; /* set to point to result */ + unsigned len; /* set to length of result */ +} sasl_interact_t; + +typedef struct sasl_client_plug { + /* mechanism name */ + const char *mech_name; + + /* best mech additional security layer strength factor */ + sasl_ssf_t max_ssf; + + /* best security flags, as defined in sasl_security_properties_t */ + unsigned security_flags; + + /* features of plugin */ + unsigned features; + + /* required prompt ids, NULL = user/pass only */ + const unsigned long *required_prompts; + + /* global state for mechanism */ + void *glob_context; + + /* create context for mechanism, using params supplied + * glob_context -- from above + * params -- params from sasl_client_new + * conn_context -- context for one connection + * returns: + * SASL_OK -- success + * SASL_NOMEM -- not enough memory + * SASL_WRONGMECH -- mech doesn't support security params + */ + int (*mech_new)(void *glob_context, + sasl_client_params_t *cparams, + void **conn_context); + + /* perform one step of exchange. NULL is passed for serverin on + * first step. + * returns: + * SASL_OK -- success + * SASL_INTERACT -- user interaction needed to fill in prompts + * SASL_BADPROT -- server protocol incorrect/cancelled + * SASL_BADSERV -- server failed mutual auth + */ + int (*mech_step)(void *conn_context, + sasl_client_params_t *cparams, + const char *serverin, + unsigned serverinlen, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen, + sasl_out_params_t *oparams); + + /* dispose of connection context from mech_new + */ + void (*mech_dispose)(void *conn_context, const sasl_utils_t *utils); + + /* free all global space used by mechanism + * mech_dispose must be called on all mechanisms first + */ + void (*mech_free)(void *glob_context, const sasl_utils_t *utils); + + /* perform precalculations during a network round-trip + * or idle period. conn_context may be NULL + * returns 1 if action taken, 0 if no action taken + */ + int (*idle)(void *glob_context, + void *conn_context, + sasl_client_params_t *cparams); + + /* for additions which don't require a version upgrade; set to 0 */ + int (*spare_fptr1)(void); + int (*spare_fptr2)(void); +} sasl_client_plug_t; + +typedef int sasl_client_plug_init_t(const sasl_utils_t *utils, + int max_version, + int *out_version, + sasl_client_plug_t **pluglist, + int *plugcount); + +typedef struct client_sasl_mechanism { + int version; + char *plugname; + const sasl_client_plug_t *plug; +} client_sasl_mechanism_t; + +typedef struct cmechanism { + client_sasl_mechanism_t m; + struct cmechanism *next; +} cmechanism_t; + +typedef struct sasl_client_conn { + sasl_conn_t base; /* parts common to server + client */ + + cmechanism_t *mech; + sasl_client_params_t *cparams; + + char *clientFQDN; + + cmechanism_t *mech_list; /* list of available mechanisms */ + int mech_length; /* number of available mechanisms */ +} sasl_client_conn_t; + +GET_SET_IN_FUNCS(_sasl_locate_entry) +GET_SET_IN_FUNCS(dlsym) + +#define FIX_MACPORTS_CYRUS_SASL_BUG 1 + +void *Hooked_dlsym(void* handle, const char* symbol) +{ + set_in_dlsym(true); + +#ifdef FIX_MACPORTS_CYRUS_SASL_BUG + if ((get_in_dlsym_count() == 1) && get_in__sasl_locate_entry()) { + if (symbol && (symbol[0]== '_')) { + ++symbol; + } + } +#endif + + void *retval = dlsym(handle, symbol); + + if ((get_in_dlsym_count() == 1) && get_in__sasl_locate_entry()) { + LogWithFormat(true, "Hook.mm: dlsym(): handle %p, symbol %s, returning %p", + handle, symbol, retval); + } + + set_in_dlsym(false); + return retval; +} + +int (*_sasl_locate_entry_caller)(void *library, const char *entryname, + void **entry_point) = NULL; + +int Hooked__sasl_locate_entry(void *library, const char *entryname, + void **entry_point) +{ + set_in__sasl_locate_entry(true); + + int retval = _sasl_locate_entry_caller(library, entryname, entry_point); + + LogWithFormat(true, "Hook.mm: _sasl_locate_entry(): library %p, entryname %s, entry_point %p, returning %i", + library, entryname ? entryname : "[null]", entry_point ? *entry_point : NULL, retval); + + set_in__sasl_locate_entry(false); + return retval; +} + +int (*_sasl_get_plugin_caller)(const char *file, + const sasl_callback_t *verifyfile_cb, + void **libraryptr) = NULL; + +int Hooked__sasl_get_plugin(const char *file, + const sasl_callback_t *verifyfile_cb, + void **libraryptr) +{ + int retval = _sasl_get_plugin_caller(file, verifyfile_cb, libraryptr); + + LogWithFormat(true, "Hook.mm: _sasl_get_plugin(): file %s, library %p, returning %i", + file ? file : "[null]", libraryptr ? *libraryptr : NULL, retval); + //PrintStackTrace(); + + return retval; +} + +int (*sasl_client_add_plugin_caller)(const char *plugname, + sasl_client_plug_init_t *entry_point) = NULL; + +int Hooked_sasl_client_add_plugin(const char *plugname, + sasl_client_plug_init_t *entry_point) +{ + int retval = sasl_client_add_plugin_caller(plugname, entry_point); + + LogWithFormat(true, "Hook.mm: sasl_client_add_plugin(): plugname %s, entry_point %p, returning %i", + plugname ? plugname : "[null]", entry_point, retval); + //PrintStackTrace(); + + return retval; +} + +int (*sasl_client_new_caller)(const char *service, + const char *serverFQDN, + const char *iplocalport, + const char *ipremoteport, + const sasl_callback_t *prompt_supp, + unsigned flags, + sasl_conn_t **pconn) = NULL; + +int Hooked_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) +{ + int retval = sasl_client_new_caller(service, serverFQDN, + iplocalport, ipremoteport, + prompt_supp, flags, pconn); + + LogWithFormat(true, "Hook.mm: sasl_client_new(1): service %s, serverFQDN %s, iplocalport %s, ipremoteport %s, flags 0x%x, returning %i", + service ? service : "[null]", serverFQDN ? serverFQDN : "[null]", + iplocalport ? iplocalport : "[null]", ipremoteport ? ipremoteport : "[null]", + flags, retval); + + sasl_getopt_t *getopt = NULL; + void *context = NULL; + for (const sasl_callback_t *callback = prompt_supp; callback->id != SASL_CB_LIST_END; ++callback) { + LogWithFormat(false, " prompt_supp id 0x%lx, proc %p, context %p", + callback->id, callback->proc, callback->context); + if (callback->id == SASL_CB_GETOPT) { + getopt = (sasl_getopt_t *) callback->proc; + context = callback->context; + } + } + + const char *client_mech_list = NULL; + if (getopt) { + getopt(context, NULL, "client_mech_list", &client_mech_list, NULL); + } + LogWithFormat(true, "Hook.mm: sasl_client_new(2): client_mech_list %s", + client_mech_list ? client_mech_list : "[null]"); + + return retval; +} + +int (*sasl_client_start_caller)(sasl_conn_t *conn, + const char *mechlist, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen, + const char **mech) = NULL; + +int Hooked_sasl_client_start(sasl_conn_t *conn, + const char *mechlist, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen, + const char **mech) +{ + sasl_client_conn_t *c_conn = (sasl_client_conn_t *) conn; + + int retval = sasl_client_start_caller(conn, mechlist, prompt_need, + clientout, clientoutlen, mech); + + LogWithFormat(true, "Hook.mm: sasl_client_start(1): type %u, flags %x, props (min_ssf %u, max_ssf %u, security_flags 0x%x), external (ssf %u, auth_id %s), mechlist %s, returning 0x%x", + conn ? conn->type : -1, conn ? conn->flags : -1, + conn ? conn->props.min_ssf : -1, + conn ? conn->props.max_ssf : -1, + conn ? conn->props.security_flags : -1, + conn ? conn->external.ssf : -1, + conn ? (conn->external.auth_id ? conn->external.auth_id : "[null]") : "[null]", + mechlist ? mechlist : "[null]", + retval); + + cmechanism_t *conn_mechs = NULL; + int conn_mechs_length = 0; + if (c_conn) { + conn_mechs = c_conn->mech_list; + conn_mechs_length = c_conn->mech_length; + } + LogWithFormat(true, "Hook.mm: sasl_client_start(2): conn_mechs %p, conn_mechs_length %i", + conn_mechs, conn_mechs_length); + for (cmechanism_t *m = conn_mechs; m != NULL; m = m->next) { + LogWithFormat(false, " plugin mech_name %s", m->m.plug->mech_name); + } + + return retval; +} + +int (*_sasl_is_equal_mech_caller)(const char *req_mech, + const char *plug_mech, + size_t req_mech_len, + int *plus) = NULL; + +int Hooked__sasl_is_equal_mech(const char *req_mech, + const char *plug_mech, + size_t req_mech_len, + int *plus) +{ + int retval = _sasl_is_equal_mech_caller(req_mech, plug_mech, req_mech_len, plus); + + LogWithFormat(true, "Hook.mm: _sasl_is_equal_mech(): req_mech %s, plug_mech %s, req_mech_len %lu, plus %i, returning %i", + req_mech ? req_mech : "[null]", plug_mech ? plug_mech : "[null]", + req_mech_len, plus ? *plus : -1, retval); + + return retval; +} + #pragma mark - typedef struct _hook_desc { @@ -1232,6 +1976,14 @@ __attribute__((used)) static const hook_desc user_hooks[] INTERPOSE_FUNCTION(NSPushAutoreleasePool), PATCH_FUNCTION(__CFInitialize, /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation), PATCH_FUNCTION(__CFGetConverter, /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation), + + INTERPOSE_FUNCTION(dlsym), + PATCH_FUNCTION(_sasl_locate_entry, /opt/local/lib/libsasl2.3.dylib), + PATCH_FUNCTION(_sasl_get_plugin, /opt/local/lib/libsasl2.3.dylib), + PATCH_FUNCTION(sasl_client_add_plugin, /opt/local/lib/libsasl2.3.dylib), + PATCH_FUNCTION(sasl_client_new, /opt/local/lib/libsasl2.3.dylib), + PATCH_FUNCTION(sasl_client_start, /opt/local/lib/libsasl2.3.dylib), + PATCH_FUNCTION(_sasl_is_equal_mech, /opt/local/lib/libsasl2.3.dylib), }; // What follows are declarations of the CoreSymbolication APIs that we use to