pluginviewer.c | pluginviewer.c | |||
---|---|---|---|---|
/* pluginviewer.c -- Plugin Viewer for CMU SASL | /* pluginviewer.c -- Plugin Viewer for CMU SASL | |||
* Alexey Melnikov, Isode Ltd. | * Alexey Melnikov, Isode Ltd. | |||
* | * | |||
* $Id: pluginviewer.c,v 1.4 2006/04/26 15:34:34 mel Exp $ | * $Id: pluginviewer.c,v 1.11 2011/09/01 14:12:18 mel Exp $ | |||
*/ | */ | |||
/* | /* | |||
* Copyright (c) 2004 Carnegie Mellon University. All rights reserved. | * Copyright (c) 2004 Carnegie Mellon University. All rights reserved. | |||
* | * | |||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | |||
* are met: | * are met: | |||
* | * | |||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | * notice, this list of conditions and the following disclaimer. | |||
skipping to change at line 96 | skipping to change at line 96 | |||
#ifndef HAVE_GETSUBOPT | #ifndef HAVE_GETSUBOPT | |||
int getsubopt(char **optionp, const char * const *tokens, char **valuep); | int getsubopt(char **optionp, const char * const *tokens, char **valuep); | |||
#endif | #endif | |||
static const char | static const char | |||
build_ident[] = "$Build: pluginviewer " PACKAGE "-" VERSION " $"; | build_ident[] = "$Build: pluginviewer " PACKAGE "-" VERSION " $"; | |||
static const char *progname = NULL; | static const char *progname = NULL; | |||
/* SASL authentication methods (client or server side). NULL means all. */ | /* SASL authentication methods (client or server side). NULL means all. */ | |||
static char *mech = NULL; | static char *sasl_mech = NULL; | |||
/* auxprop methods. NULL means all. */ | /* auxprop methods. NULL means all. */ | |||
static char *auxprop_mech = NULL; | static char *auxprop_mech = NULL; | |||
#define N_CALLBACKS (16) | #define N_CALLBACKS (16) | |||
#define NOT_NULL (void *) -1 | #define NOT_NULL (void *) -1 | |||
#define SAMPLE_SEC_BUF_SIZE (2048) | #define SAMPLE_SEC_BUF_SIZE (2048) | |||
static const char *bit_subopts[] = { | static const char *bit_subopts[] = { | |||
skipping to change at line 138 | skipping to change at line 138 | |||
"nodict", | "nodict", | |||
#define OPT_FORWARDSEC (3) | #define OPT_FORWARDSEC (3) | |||
"forwardsec", | "forwardsec", | |||
#define OPT_NOANONYMOUS (4) | #define OPT_NOANONYMOUS (4) | |||
"noanonymous", | "noanonymous", | |||
#define OPT_PASSCRED (5) | #define OPT_PASSCRED (5) | |||
"passcred", | "passcred", | |||
NULL | NULL | |||
}; | }; | |||
static const char *ip_subopts[] = { | ||||
#define OPT_IP_LOCAL (0) | ||||
"local", | ||||
#define OPT_IP_REMOTE (1) | ||||
"remote", | ||||
NULL | ||||
}; | ||||
/* Whitespace separated list of mechanisms to allow (e.g. 'plain otp'). | /* Whitespace separated list of mechanisms to allow (e.g. 'plain otp'). | |||
Used to restrict the mechanisms to a subset of the installed plugins. | Used to restrict the mechanisms to a subset of the installed plugins. | |||
Default: NULL (i.e. all available) */ | Default: NULL (i.e. all available) */ | |||
#define SASL_OPT_MECH_LIST "mech_list" | #define SASL_OPT_MECH_LIST "mech_list" | |||
/* Name of canon_user plugin to use, default is "INTERNAL" */ | /* Name of canon_user plugin to use, default is "INTERNAL" */ | |||
#define SASL_OPT_CANON_USER_PLUGIN "canon_user_plugin" | #define SASL_OPT_CANON_USER_PLUGIN "canon_user_plugin" | |||
/* Name of auxiliary plugin to use, you may specify a space-separated list | /* Name of auxiliary plugin to use, you may specify a space-separated list | |||
of plugin names, and the plugins will be queried in order. Default is NU LL (i.e. query all) */ | of plugin names, and the plugins will be queried in order. Default is NU LL (i.e. query all) */ | |||
#define SASL_OPT_AUXPROP_PLUGIN "auxprop_plugin" | #define SASL_OPT_AUXPROP_PLUGIN "auxprop_plugin" | |||
skipping to change at line 219 | skipping to change at line 211 | |||
if (searchpath) { | if (searchpath) { | |||
*path = searchpath; | *path = searchpath; | |||
} else { | } else { | |||
*path = PLUGINDIR; | *path = PLUGINDIR; | |||
} | } | |||
return SASL_OK; | return SASL_OK; | |||
} | } | |||
static int | static int | |||
sasl_getopt ( | plugview_sasl_getopt ( | |||
void *context, | void *context, | |||
const char *plugin_name, | const char *plugin_name, | |||
const char *option, | const char *option, | |||
const char **result, | const char **result, | |||
unsigned *len | unsigned *len | |||
) | ) | |||
{ | { | |||
if (strcasecmp (option, SASL_OPT_MECH_LIST) == 0) { | if (strcasecmp (option, SASL_OPT_MECH_LIST) == 0) { | |||
/* Whitespace separated list of mechanisms to allow (e.g. 'plain ot p'). | /* Whitespace separated list of mechanisms to allow (e.g. 'plain ot p'). | |||
Used to restrict the mechanisms to a subset of the installed plu gins. | Used to restrict the mechanisms to a subset of the installed plu gins. | |||
Default: NULL (i.e. all available) */ | Default: NULL (i.e. all available) */ | |||
if (result != NULL) { | if (result != NULL) { | |||
*result = mech; | *result = sasl_mech; | |||
} | } | |||
if (len != NULL) { | if (len != NULL) { | |||
/* This might be NULL, which means "all mechanisms" */ | /* This might be NULL, which means "all mechanisms" */ | |||
*len = mech ? strlen(mech) : 0; | *len = sasl_mech ? strlen(sasl_mech) : 0; | |||
} | } | |||
return (SASL_OK); | return (SASL_OK); | |||
} | } | |||
else { | else { | |||
/* Unrecognized */ | /* Unrecognized */ | |||
return (SASL_FAIL); | return (SASL_FAIL); | |||
} | } | |||
} | } | |||
static void | static void | |||
skipping to change at line 281 | skipping to change at line 273 | |||
} | } | |||
static void | static void | |||
fail(const char *what) | fail(const char *what) | |||
{ | { | |||
fprintf(stderr, "%s: %s\n", | fprintf(stderr, "%s: %s\n", | |||
progname, what); | progname, what); | |||
exit(EXIT_FAILURE); | exit(EXIT_FAILURE); | |||
} | } | |||
static void | ||||
osfail() | ||||
{ | ||||
perror(progname); | ||||
exit(EXIT_FAILURE); | ||||
} | ||||
/* Produce a space separated list of installed mechanisms */ | /* Produce a space separated list of installed mechanisms */ | |||
static void | static void | |||
list_installed_server_mechanisms ( | list_installed_server_mechanisms ( | |||
server_sasl_mechanism_t *m, | server_sasl_mechanism_t *m, | |||
sasl_info_callback_stage_t stage, | sasl_info_callback_stage_t stage, | |||
void *rock | void *rock | |||
) | ) | |||
{ | { | |||
char ** list_of_mechs = (char **) rock; | char ** list_of_mechs = (char **) rock; | |||
char * new_list; | char * new_list; | |||
skipping to change at line 382 | skipping to change at line 367 | |||
{ | { | |||
int c = 0; | int c = 0; | |||
int errflag = 0; | int errflag = 0; | |||
int result; | int result; | |||
sasl_security_properties_t secprops; | sasl_security_properties_t secprops; | |||
sasl_ssf_t extssf = 0; | sasl_ssf_t extssf = 0; | |||
const char *ext_authid = NULL; | const char *ext_authid = NULL; | |||
char *options, *value; | char *options, *value; | |||
const char *available_mechs = NULL; | const char *available_mechs = NULL; | |||
unsigned len; | unsigned len; | |||
unsigned count; | int count; | |||
sasl_callback_t callbacks[N_CALLBACKS], *callback; | sasl_callback_t callbacks[N_CALLBACKS], *callback; | |||
char *searchpath = NULL; | char *searchpath = NULL; | |||
char *service = "test"; | char *service = "test"; | |||
char * list_of_server_mechs = NULL; | char * list_of_server_mechs = NULL; | |||
char * list_of_client_mechs = NULL; | char * list_of_client_mechs = NULL; | |||
char * list_of_auxprop_mechs = NULL; | char * list_of_auxprop_mechs = NULL; | |||
int list_all_plugins = 1; /* By default we list all plugins * / | int list_all_plugins = 1; /* By default we list all plugins * / | |||
int list_client_auth_plugins = 0; | int list_client_auth_plugins = 0; | |||
int list_server_auth_plugins = 0; | int list_server_auth_plugins = 0; | |||
int list_auxprop_plugins = 0; | int list_auxprop_plugins = 0; | |||
skipping to change at line 488 | skipping to change at line 473 | |||
} | } | |||
break; | break; | |||
default: | default: | |||
errflag = 1; | errflag = 1; | |||
break; | break; | |||
} | } | |||
} | } | |||
break; | break; | |||
case 'm': | case 'm': | |||
mech = optarg; | sasl_mech = optarg; | |||
break; | break; | |||
case 'f': | case 'f': | |||
options = optarg; | options = optarg; | |||
while (*options != '\0') { | while (*options != '\0') { | |||
switch(getsubopt(&options, (const char * const *)flag_subopt s, &value)) { | switch(getsubopt(&options, (const char * const *)flag_subopt s, &value)) { | |||
case OPT_NOPLAIN: | case OPT_NOPLAIN: | |||
secprops.security_flags |= SASL_SEC_NOPLAINTEXT; | secprops.security_flags |= SASL_SEC_NOPLAINTEXT; | |||
break; | break; | |||
case OPT_NOACTIVE: | case OPT_NOACTIVE: | |||
skipping to change at line 539 | skipping to change at line 524 | |||
if (optind != argc) { | if (optind != argc) { | |||
/* We don't *have* extra arguments */ | /* We don't *have* extra arguments */ | |||
errflag = 1; | errflag = 1; | |||
} | } | |||
if (errflag) { | if (errflag) { | |||
fprintf(stderr, "%s: Usage: %s [-a] [-s] [-c] [-b min=N,max=N] [-e ssf=N,id=ID] [-m MECHS] [-x AUXPROP_MECH] [-f FLAGS] [-i local=IP,remote=IP ] [-p PATH]\n" | fprintf(stderr, "%s: Usage: %s [-a] [-s] [-c] [-b min=N,max=N] [-e ssf=N,id=ID] [-m MECHS] [-x AUXPROP_MECH] [-f FLAGS] [-i local=IP,remote=IP ] [-p PATH]\n" | |||
"\t-a\tlist auxprop plugins\n" | "\t-a\tlist auxprop plugins\n" | |||
"\t-s\tlist server authentication (SASL) plugins\n" | "\t-s\tlist server authentication (SASL) plugins\n" | |||
"\t-s\tlist client authentication (SASL) plugins\n" | "\t-c\tlist client authentication (SASL) plugins\n" | |||
"\t-b ...\t#bits to use for encryption\n" | "\t-b ...\t#bits to use for encryption\n" | |||
"\t\tmin=N\tminumum #bits to use (1 => integrity)\n" | "\t\tmin=N\tminumum #bits to use (1 => integrity)\n" | |||
"\t\tmax=N\tmaximum #bits to use\n" | "\t\tmax=N\tmaximum #bits to use\n" | |||
"\t-e ...\tassume external encryption\n" | "\t-e ...\tassume external encryption\n" | |||
"\t\tssf=N\texternal mech provides N bits of encryption\n" | "\t\tssf=N\texternal mech provides N bits of encryption\n" | |||
"\t\tid=ID\texternal mech provides authentication id ID\n" | "\t\tid=ID\texternal mech provides authentication id ID\n" | |||
"\t-m MECHS\tforce to use one of MECHS SASL mechanism\n" | "\t-m MECHS\tforce to use one of MECHS SASL mechanism\n" | |||
"\t-x AUXPROP_MECHS\tforce to use one of AUXPROP_MECHS auxpr op plugins\n" | "\t-x AUXPROP_MECHS\tforce to use one of AUXPROP_MECHS auxpr op plugins\n" | |||
"\t-f ...\tset security flags\n" | "\t-f ...\tset security flags\n" | |||
"\t\tnoplain\t\tno plaintext password send during authentica tion\n" | "\t\tnoplain\t\tno plaintext password send during authentica tion\n" | |||
"\t\tnoactive\trequire security vs. active attacks\n" | "\t\tnoactive\trequire security vs. active attacks\n" | |||
"\t\tnodict\t\trequire security vs. passive dictionary attac ks\n" | "\t\tnodict\t\trequire security vs. passive dictionary attac ks\n" | |||
"\t\tforwardsec\trequire forward secrecy\n" | "\t\tforwardsec\trequire forward secrecy\n" | |||
"\t\tmaximum\t\trequire all security flags\n" | "\t\tmaximum\t\trequire all security flags\n" | |||
"\t\tpasscred\tattempt to pass client credentials\n" | "\t\tpasscred\tattempt to pass client credentials\n" | |||
#ifdef WIN32 | #ifdef WIN32 | |||
"\t-p PATH\tsemicolon-separated search path for mechanisms\n ", | "\t-p PATH\tsemicolon-separated search path for mechanisms\n ", | |||
#else | #else | |||
"\t-p PATH\tcolon-seperated search path for mechanisms\n", | "\t-p PATH\tcolon-separated search path for mechanisms\n", | |||
#endif | #endif | |||
progname, progname); | progname, progname); | |||
exit(EXIT_FAILURE); | exit(EXIT_FAILURE); | |||
} | } | |||
/* Fill in the callbacks that we're providing... */ | /* Fill in the callbacks that we're providing... */ | |||
callback = callbacks; | callback = callbacks; | |||
/* log */ | /* log */ | |||
callback->id = SASL_CB_LOG; | callback->id = SASL_CB_LOG; | |||
callback->proc = &sasl_my_log; | callback->proc = (sasl_callback_ft)&sasl_my_log; | |||
callback->context = NULL; | callback->context = NULL; | |||
++callback; | ++callback; | |||
/* getpath */ | /* getpath */ | |||
if (searchpath) { | if (searchpath) { | |||
callback->id = SASL_CB_GETPATH; | callback->id = SASL_CB_GETPATH; | |||
callback->proc = &getpath; | callback->proc = (sasl_callback_ft)&getpath; | |||
callback->context = searchpath; | callback->context = searchpath; | |||
++callback; | ++callback; | |||
} | } | |||
/* getopt */ | /* getopt */ | |||
/* NOTE: this will return "sasl_mech" option, however this HAS NO EFFEC | ||||
T | ||||
on client side SASL plugins, which just never query this option */ | ||||
callback->id = SASL_CB_GETOPT; | callback->id = SASL_CB_GETOPT; | |||
callback->proc = &sasl_getopt; | callback->proc = (sasl_callback_ft)&plugview_sasl_getopt; | |||
callback->context = NULL; | callback->context = NULL; | |||
++callback; | ++callback; | |||
/* The following callbacks are for a client connection only. | /* The following callbacks are for a client connection only. | |||
We reuse the same callbacks variable and the server side doesn't like | We reuse the same callbacks variable and the server side doesn't like | |||
proc == NULL. So we just put something there, != NULL! */ | proc == NULL. So we just put something there, != NULL! */ | |||
callback->id = SASL_CB_AUTHNAME; | callback->id = SASL_CB_AUTHNAME; | |||
callback->proc = NOT_NULL; | callback->proc = NOT_NULL; | |||
callback->context = NULL; | callback->context = NULL; | |||
++callback; | ++callback; | |||
skipping to change at line 622 | skipping to change at line 609 | |||
result = sasl_client_init(callbacks); | result = sasl_client_init(callbacks); | |||
if (result != SASL_OK) { | if (result != SASL_OK) { | |||
saslfail(result, "Initializing client side of libsasl", NULL); | saslfail(result, "Initializing client side of libsasl", NULL); | |||
} | } | |||
result = sasl_server_init(callbacks, "pluginviewer"); | result = sasl_server_init(callbacks, "pluginviewer"); | |||
if (result != SASL_OK) { | if (result != SASL_OK) { | |||
saslfail(result, "Initializing server side of libsasl", NULL); | saslfail(result, "Initializing server side of libsasl", NULL); | |||
} | } | |||
if (list_all_plugins || list_server_auth_plugins) { | if (list_all_plugins || list_auxprop_plugins) { | |||
list_of_auxprop_mechs = NULL; | ||||
auxprop_plugin_info (NULL, /* list all auxprop mechanisms */ | ||||
&list_installed_auxprop_mechanisms, | ||||
(void *) &list_of_auxprop_mechs); | ||||
printf ("Installed and properly configured auxprop mechanisms are:\n | ||||
%s\n", | ||||
(list_of_auxprop_mechs == NULL) ? "<none>" : list_of_auxprop | ||||
_mechs); | ||||
free (list_of_auxprop_mechs); | ||||
auxprop_plugin_info (auxprop_mech, NULL, NULL); | ||||
} | ||||
/* TODO: add listing of canonicalization plugins, if needed. */ | ||||
if (list_all_plugins || list_server_auth_plugins) { | ||||
/* SASL server plugins */ | /* SASL server plugins */ | |||
/* List all loaded plugins first */ | ||||
list_of_server_mechs = NULL; | ||||
sasl_server_plugin_info (NULL, /* list all SASL mechanisms */ | ||||
&list_installed_server_mechanisms, | ||||
(void *) &list_of_server_mechs); | ||||
printf ("Installed and properly configured SASL (server side) mecha | ||||
nisms are:\n %s\n", list_of_server_mechs); | ||||
free (list_of_server_mechs); | ||||
/* Now list plugins matching the criteria */ | ||||
result = sasl_server_new(service, | result = sasl_server_new(service, | |||
/* Has to be any non NULL value */ | /* Has to be any non NULL value */ | |||
"test.example.com", /* localdomain */ | "test.example.com", /* localdomain */ | |||
NULL, /* userdomain */ | NULL, /* userdomain */ | |||
NULL, /* iplocal */ | NULL, /* iplocal */ | |||
NULL, /* ipremote */ | NULL, /* ipremote */ | |||
NULL, | NULL, | |||
0, | 0, | |||
&server_conn); | &server_conn); | |||
if (result != SASL_OK) { | if (result != SASL_OK) { | |||
saslfail(result, "Allocating sasl connection state (server side )", NULL); | saslfail(result, "Allocating sasl connection state (server side )", NULL); | |||
} | } | |||
/* The following two options are required for SSF */ | /* The following two options are required for SASL EXTERNAL */ | |||
if (extssf) { | if (extssf) { | |||
result = sasl_setprop(server_conn, | result = sasl_setprop(server_conn, | |||
SASL_SSF_EXTERNAL, | SASL_SSF_EXTERNAL, | |||
&extssf); | &extssf); | |||
if (result != SASL_OK) { | if (result != SASL_OK) { | |||
saslfail(result, "Setting external SSF", NULL); | saslfail(result, "Setting external SSF", NULL); | |||
} | } | |||
} | } | |||
skipping to change at line 667 | skipping to change at line 682 | |||
} | } | |||
result = sasl_setprop(server_conn, | result = sasl_setprop(server_conn, | |||
SASL_SEC_PROPS, | SASL_SEC_PROPS, | |||
&secprops); | &secprops); | |||
if (result != SASL_OK) { | if (result != SASL_OK) { | |||
saslfail(result, "Setting security properties", NULL); | saslfail(result, "Setting security properties", NULL); | |||
} | } | |||
/* This will use getopt callback, which is using the "mech" global variable */ | /* NOTE - available_mechs must not be freed */ | |||
result = sasl_listmech(server_conn, | result = sasl_listmech(server_conn, | |||
ext_authid, | ext_authid, | |||
NULL, | NULL, | |||
" ", | " ", | |||
NULL, | NULL, | |||
&available_mechs, | &available_mechs, | |||
&len, | &len, | |||
&count); | &count); | |||
if (result != SASL_OK) { | if (result != SASL_OK) { | |||
saslfail(result, "Setting security properties", NULL); | saslfail(result, "Listing SASL mechanisms", NULL); | |||
} | } | |||
if (count > 0) { | /* NOTE: available_mechs contains subset of sasl_mech */ | |||
list_of_server_mechs = NULL; | ||||
sasl_server_plugin_info (NULL, /* list all SASL mechanisms */ | ||||
&list_installed_server_mechanisms, | ||||
(void *) &list_of_server_mechs); | ||||
printf ("Installed SASL (server side) mechanisms are:\n%s\n", l | if (count > 0) { | |||
ist_of_server_mechs); | printf ("Available SASL (server side) mechanisms matching your | |||
criteria are:\n %s\n", available_mechs); | ||||
free (list_of_server_mechs); | ||||
/* Dump information about the requested SASL mechanism */ | /* Dump information about the requested SASL mechanism */ | |||
/* NOTE - available_mechs must not be freed */ | ||||
sasl_server_plugin_info (available_mechs, NULL, NULL); | sasl_server_plugin_info (available_mechs, NULL, NULL); | |||
} else { | } else { | |||
printf ("No server side SASL mechanisms installed\n"); | printf ("No server side SASL mechanisms matching your criteria f ound\n"); | |||
} | } | |||
} | } | |||
if (list_all_plugins || list_auxprop_plugins) { | if (list_all_plugins || list_client_auth_plugins) { | |||
list_of_auxprop_mechs = NULL; | /* SASL client plugins */ | |||
/* List all loaded plugins first */ | ||||
auxprop_plugin_info (NULL, /* list all auxprop mechanisms */ | list_of_client_mechs = NULL; | |||
&list_installed_auxprop_mechanisms, | ||||
(void *) &list_of_auxprop_mechs); | ||||
printf ("Installed auxprop mechanisms are:\n%s\n", list_of_auxprop_m | ||||
echs); | ||||
free (list_of_auxprop_mechs); | sasl_client_plugin_info (NULL, /* list all SASL mechanisms */ | |||
&list_installed_client_mechanisms, | ||||
(void *) &list_of_client_mechs); | ||||
auxprop_plugin_info (auxprop_mech, NULL, NULL); | printf ("Installed and properly configured SASL (client side) mechan | |||
} | isms are:\n %s\n", | |||
(list_of_client_mechs != NULL) ? list_of_client_mechs : "<no | ||||
ne>"); | ||||
/* TODO: add listing of canonicalization plugins, if needed. */ | free (list_of_client_mechs); | |||
if (list_all_plugins || list_client_auth_plugins) { | /* Now list plugins matching the criteria */ | |||
/* SASL client plugins */ | ||||
result = sasl_client_new(service, | result = sasl_client_new(service, | |||
/* Has to be any non NULL value */ | /* Has to be any non NULL value */ | |||
"test.example.com", /* fqdn */ | "test.example.com", /* fqdn */ | |||
NULL, /* iplocal */ | NULL, /* iplocal */ | |||
NULL, /* ipremote */ | NULL, /* ipremote */ | |||
NULL, | NULL, | |||
0, | 0, | |||
&client_conn); | &client_conn); | |||
if (result != SASL_OK) { | if (result != SASL_OK) { | |||
skipping to change at line 759 | skipping to change at line 764 | |||
} | } | |||
result = sasl_setprop(client_conn, | result = sasl_setprop(client_conn, | |||
SASL_SEC_PROPS, | SASL_SEC_PROPS, | |||
&secprops); | &secprops); | |||
if (result != SASL_OK) { | if (result != SASL_OK) { | |||
saslfail(result, "Setting security properties", NULL); | saslfail(result, "Setting security properties", NULL); | |||
} | } | |||
/* This will use getopt callback, which is using the "mech" global variable */ | /* NOTE - available_mechs must not be freed */ | |||
result = sasl_listmech(client_conn, | result = sasl_listmech(client_conn, | |||
ext_authid, | ext_authid, | |||
NULL, | NULL, | |||
" ", | " ", | |||
NULL, | NULL, | |||
&available_mechs, | &available_mechs, | |||
&len, | &len, | |||
&count); | &count); | |||
if (result != SASL_OK) { | if (result != SASL_OK) { | |||
saslfail(result, "Setting security properties", NULL); | saslfail(result, "Listing SASL mechanisms", NULL); | |||
} | } | |||
if (count > 0) { | if (count > 0) { | |||
list_of_client_mechs = NULL; | printf ("Available SASL (client side) mechanisms matching your | |||
criteria are:\n %s\n", available_mechs); | ||||
sasl_client_plugin_info (NULL, /* list all SASL mechanisms */ | ||||
&list_installed_client_mechanisms, | ||||
(void *) &list_of_client_mechs); | ||||
printf ("Installed SASL (client side) mechanisms are:\n%s\n", li | ||||
st_of_client_mechs); | ||||
free (list_of_client_mechs); | ||||
/* Dump information about the requested SASL mechanism */ | /* Dump information about the requested SASL mechanism */ | |||
/* NOTE - available_mechs must not be freed */ | sasl_client_plugin_info (sasl_mech, NULL, NULL); | |||
sasl_client_plugin_info (available_mechs, NULL, NULL); | ||||
} else { | } else { | |||
printf ("No client side SASL mechanisms installed\n"); | printf ("No client side SASL mechanisms matching your criteria f ound\n"); | |||
} | } | |||
} | } | |||
free_conn(); | free_conn(); | |||
/* Call sasl_done twice - one for the client side SASL and | /* Call sasl_done twice - one for the client side SASL and | |||
one for the server side. */ | one for the server side. */ | |||
sasl_done(); | sasl_done(); | |||
sasl_done(); | sasl_done(); | |||
#ifdef WIN32 | #ifdef WIN32 | |||
End of changes. 36 change blocks. | ||||
80 lines changed or deleted | 81 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |