auxprop.c | auxprop.c | |||
---|---|---|---|---|
/* auxprop.c - auxilliary property support | /* auxprop.c - auxilliary property support | |||
* Rob Siemborski | * Rob Siemborski | |||
* $Id: auxprop.c,v 1.16 2006/03/14 14:23:55 mel Exp $ | * $Id: auxprop.c,v 1.21 2011/09/01 14:12:53 mel Exp $ | |||
*/ | */ | |||
/* | /* | |||
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved . | * Copyright (c) 1998-2003 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 49 | skipping to change at line 49 | |||
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | |||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | |||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
*/ | */ | |||
#include <config.h> | #include <config.h> | |||
#include <sasl.h> | #include <sasl.h> | |||
#include <prop.h> | #include <prop.h> | |||
#include <ctype.h> | #include <ctype.h> | |||
#include <stdio.h> | ||||
#include "saslint.h" | #include "saslint.h" | |||
struct proppool | struct proppool | |||
{ | { | |||
struct proppool *next; | struct proppool *next; | |||
size_t size; /* Size of Block */ | size_t size; /* Size of Block */ | |||
size_t unused; /* Space unused in this pool between end | size_t unused; /* Space unused in this pool between end | |||
* of char** area and beginning of char* area */ | * of char** area and beginning of char* area */ | |||
skipping to change at line 810 | skipping to change at line 811 | |||
int sasl_auxprop_add_plugin(const char *plugname, | int sasl_auxprop_add_plugin(const char *plugname, | |||
sasl_auxprop_init_t *auxpropfunc) | sasl_auxprop_init_t *auxpropfunc) | |||
{ | { | |||
int result, out_version; | int result, out_version; | |||
auxprop_plug_list_t *new_item; | auxprop_plug_list_t *new_item; | |||
sasl_auxprop_plug_t *plug; | sasl_auxprop_plug_t *plug; | |||
result = auxpropfunc(sasl_global_utils, SASL_AUXPROP_PLUG_VERSION, | result = auxpropfunc(sasl_global_utils, SASL_AUXPROP_PLUG_VERSION, | |||
&out_version, &plug, plugname); | &out_version, &plug, plugname); | |||
/* Check if out_version is too old. | ||||
We only support the current at the moment */ | ||||
if (result == SASL_OK && out_version < SASL_AUXPROP_PLUG_VERSION) { | ||||
result = SASL_BADVERS; | ||||
} | ||||
if(result != SASL_OK) { | if(result != SASL_OK) { | |||
_sasl_log(NULL, SASL_LOG_ERR, "auxpropfunc error %s\n", | _sasl_log(NULL, SASL_LOG_ERR, "auxpropfunc error %s\n", | |||
sasl_errstring(result, NULL, NULL)); | sasl_errstring(result, NULL, NULL)); | |||
return result; | return result; | |||
} | } | |||
/* We require that this function is implemented */ | /* We require that this function is implemented */ | |||
if(!plug->auxprop_lookup) return SASL_BADPROT; | if(!plug->auxprop_lookup) return SASL_BADPROT; | |||
new_item = sasl_ALLOC(sizeof(auxprop_plug_list_t)); | new_item = sasl_ALLOC(sizeof(auxprop_plug_list_t)); | |||
skipping to change at line 845 | skipping to change at line 852 | |||
ptr_next = ptr->next; | ptr_next = ptr->next; | |||
if(ptr->plug->auxprop_free) | if(ptr->plug->auxprop_free) | |||
ptr->plug->auxprop_free(ptr->plug->glob_context, | ptr->plug->auxprop_free(ptr->plug->glob_context, | |||
sasl_global_utils); | sasl_global_utils); | |||
sasl_FREE(ptr); | sasl_FREE(ptr); | |||
} | } | |||
auxprop_head = NULL; | auxprop_head = NULL; | |||
} | } | |||
/* Return the updated account status based on the current ("so far") and | ||||
the specific status returned by the latest auxprop call */ | ||||
static int | ||||
_sasl_account_status (int current_status, | ||||
int specific_status) | ||||
{ | ||||
switch (specific_status) { | ||||
case SASL_NOVERIFY: | ||||
specific_status = SASL_OK; | ||||
/* fall through */ | ||||
case SASL_OK: | ||||
if (current_status == SASL_NOMECH || | ||||
current_status == SASL_NOUSER) { | ||||
current_status = specific_status; | ||||
} | ||||
break; | ||||
case SASL_NOUSER: | ||||
if (current_status == SASL_NOMECH) { | ||||
current_status = specific_status; | ||||
} | ||||
break; | ||||
/* NOTE: The disabled flag sticks, unless we hit an error */ | ||||
case SASL_DISABLED: | ||||
if (current_status == SASL_NOMECH || | ||||
current_status == SASL_NOUSER || | ||||
current_status == SASL_OK) { | ||||
current_status = specific_status; | ||||
} | ||||
break; | ||||
case SASL_NOMECH: | ||||
/* ignore */ | ||||
break; | ||||
/* SASL_UNAVAIL overrides everything */ | ||||
case SASL_UNAVAIL: | ||||
current_status = specific_status; | ||||
break; | ||||
default: | ||||
current_status = specific_status; | ||||
break; | ||||
} | ||||
return (current_status); | ||||
} | ||||
/* Do the callbacks for auxprop lookups */ | /* Do the callbacks for auxprop lookups */ | |||
void _sasl_auxprop_lookup(sasl_server_params_t *sparams, | int _sasl_auxprop_lookup(sasl_server_params_t *sparams, | |||
unsigned flags, | unsigned flags, | |||
const char *user, unsigned ulen) | const char *user, unsigned ulen) | |||
{ | { | |||
sasl_getopt_t *getopt; | sasl_getopt_t *getopt; | |||
int ret, found = 0; | int ret, found = 0; | |||
void *context; | void *context; | |||
const char *plist = NULL; | const char *plist = NULL; | |||
auxprop_plug_list_t *ptr; | auxprop_plug_list_t *ptr; | |||
int result = SASL_NOMECH; | ||||
if(_sasl_getcallback(sparams->utils->conn, | if(_sasl_getcallback(sparams->utils->conn, | |||
SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { | SASL_CB_GETOPT, | |||
(sasl_callback_ft *)&getopt, | ||||
&context) == SASL_OK) { | ||||
ret = getopt(context, NULL, "auxprop_plugin", &plist, NULL); | ret = getopt(context, NULL, "auxprop_plugin", &plist, NULL); | |||
if(ret != SASL_OK) plist = NULL; | if(ret != SASL_OK) plist = NULL; | |||
} | } | |||
if(!plist) { | if(!plist) { | |||
/* Do lookup in all plugins */ | /* Do lookup in all plugins */ | |||
/* TODO: Ideally, each auxprop plugin should be marked if its failur | ||||
e | ||||
should be ignored or treated as a fatal error of the whole lookup | ||||
. */ | ||||
for(ptr = auxprop_head; ptr; ptr = ptr->next) { | for(ptr = auxprop_head; ptr; ptr = ptr->next) { | |||
found=1; | found=1; | |||
ptr->plug->auxprop_lookup(ptr->plug->glob_context, | ret = ptr->plug->auxprop_lookup(ptr->plug->glob_context, | |||
sparams, flags, user, ulen); | sparams, flags, user, ulen); | |||
result = _sasl_account_status (result, ret); | ||||
} | } | |||
} else { | } else { | |||
char *pluginlist = NULL, *freeptr = NULL, *thisplugin = NULL; | char *pluginlist = NULL, *freeptr = NULL, *thisplugin = NULL; | |||
if(_sasl_strdup(plist, &pluginlist, NULL) != SASL_OK) return; | if(_sasl_strdup(plist, &pluginlist, NULL) != SASL_OK) return SASL_NO MEM; | |||
thisplugin = freeptr = pluginlist; | thisplugin = freeptr = pluginlist; | |||
/* Do lookup in all *specified* plugins, in order */ | /* Do lookup in all *specified* plugins, in order */ | |||
while(*thisplugin) { | while(*thisplugin) { | |||
char *p; | char *p; | |||
int last=0; | int last=0; | |||
while(*thisplugin && isspace((int)*thisplugin)) thisplugin++; | while(*thisplugin && isspace((int)*thisplugin)) thisplugin++; | |||
if(!(*thisplugin)) break; | if(!(*thisplugin)) break; | |||
skipping to change at line 894 | skipping to change at line 956 | |||
if(*p == '\0') last = 1; | if(*p == '\0') last = 1; | |||
else *p='\0'; | else *p='\0'; | |||
for(ptr = auxprop_head; ptr; ptr = ptr->next) { | for(ptr = auxprop_head; ptr; ptr = ptr->next) { | |||
/* Skip non-matching plugins */ | /* Skip non-matching plugins */ | |||
if(!ptr->plug->name | if(!ptr->plug->name | |||
|| strcasecmp(ptr->plug->name, thisplugin)) | || strcasecmp(ptr->plug->name, thisplugin)) | |||
continue; | continue; | |||
found=1; | found=1; | |||
ptr->plug->auxprop_lookup(ptr->plug->glob_context, | ret = ptr->plug->auxprop_lookup(ptr->plug->glob_context, | |||
sparams, flags, user, ulen); | sparams, flags, user, ulen); | |||
result = _sasl_account_status (result, ret); | ||||
} | } | |||
if(last) break; | if(last) break; | |||
thisplugin = p+1; | thisplugin = p+1; | |||
} | } | |||
sasl_FREE(freeptr); | sasl_FREE(freeptr); | |||
} | } | |||
if(!found) | if(!found) { | |||
_sasl_log(sparams->utils->conn, SASL_LOG_DEBUG, | _sasl_log(sparams->utils->conn, SASL_LOG_DEBUG, | |||
"could not find auxprop plugin, was searching for '%s'", | "could not find auxprop plugin, was searching for '%s'", | |||
plist ? plist : "[all]"); | plist ? plist : "[all]"); | |||
} | ||||
return result; | ||||
} | } | |||
/* Do the callbacks for auxprop stores */ | /* Do the callbacks for auxprop stores */ | |||
int sasl_auxprop_store(sasl_conn_t *conn, | int sasl_auxprop_store(sasl_conn_t *conn, | |||
struct propctx *ctx, const char *user) | struct propctx *ctx, const char *user) | |||
{ | { | |||
sasl_getopt_t *getopt; | sasl_getopt_t *getopt; | |||
int ret, found = 0; | int ret; | |||
void *context; | void *context; | |||
const char *plist = NULL; | const char *plist = NULL; | |||
auxprop_plug_list_t *ptr; | auxprop_plug_list_t *ptr; | |||
sasl_server_params_t *sparams = NULL; | sasl_server_params_t *sparams = NULL; | |||
unsigned userlen = 0; | unsigned userlen = 0; | |||
int num_constraint_violations = 0; | ||||
int total_plugins = 0; | ||||
if (ctx) { | if (ctx) { | |||
if (!conn || !user) | if (!conn || !user) | |||
return SASL_BADPARAM; | return SASL_BADPARAM; | |||
sparams = ((sasl_server_conn_t *) conn)->sparams; | sparams = ((sasl_server_conn_t *) conn)->sparams; | |||
userlen = (unsigned) strlen(user); | userlen = (unsigned) strlen(user); | |||
} | } | |||
/* Pickup getopt callback from the connection, if conn is not NULL */ | /* Pickup getopt callback from the connection, if conn is not NULL */ | |||
if(_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_O K) { | if(_sasl_getcallback(conn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { | |||
ret = getopt(context, NULL, "auxprop_plugin", &plist, NULL); | ret = getopt(context, NULL, "auxprop_plugin", &plist, NULL); | |||
if(ret != SASL_OK) plist = NULL; | if(ret != SASL_OK) plist = NULL; | |||
} | } | |||
ret = SASL_OK; | ret = SASL_OK; | |||
if(!plist) { | if(!plist) { | |||
/* Do store in all plugins */ | /* Do store in all plugins */ | |||
for(ptr = auxprop_head; ptr && ret == SASL_OK; ptr = ptr->next) { | for(ptr = auxprop_head; ptr && ret == SASL_OK; ptr = ptr->next) { | |||
found=1; | total_plugins++; | |||
if (ptr->plug->auxprop_store) | if (ptr->plug->auxprop_store) { | |||
ret = ptr->plug->auxprop_store(ptr->plug->glob_context, | ret = ptr->plug->auxprop_store(ptr->plug->glob_context, | |||
sparams, ctx, user, userlen); | sparams, ctx, user, userlen); | |||
if (ret == SASL_CONSTRAINT_VIOLAT) { | ||||
ret = SASL_OK; | ||||
num_constraint_violations++; | ||||
} | ||||
} | ||||
} | } | |||
} else { | } else { | |||
char *pluginlist = NULL, *freeptr = NULL, *thisplugin = NULL; | char *pluginlist = NULL, *freeptr = NULL, *thisplugin = NULL; | |||
if(_sasl_strdup(plist, &pluginlist, NULL) != SASL_OK) return SASL_FA IL; | if(_sasl_strdup(plist, &pluginlist, NULL) != SASL_OK) return SASL_FA IL; | |||
thisplugin = freeptr = pluginlist; | thisplugin = freeptr = pluginlist; | |||
/* Do store in all *specified* plugins, in order */ | /* Do store in all *specified* plugins, in order */ | |||
while(*thisplugin) { | while(*thisplugin) { | |||
char *p; | char *p; | |||
skipping to change at line 971 | skipping to change at line 1044 | |||
for(p = thisplugin;*p != '\0' && !isspace((int)*p); p++); | for(p = thisplugin;*p != '\0' && !isspace((int)*p); p++); | |||
if(*p == '\0') last = 1; | if(*p == '\0') last = 1; | |||
else *p='\0'; | else *p='\0'; | |||
for(ptr = auxprop_head; ptr && ret == SASL_OK; ptr = ptr->next) { | for(ptr = auxprop_head; ptr && ret == SASL_OK; ptr = ptr->next) { | |||
/* Skip non-matching plugins */ | /* Skip non-matching plugins */ | |||
if((!ptr->plug->name | if((!ptr->plug->name | |||
|| strcasecmp(ptr->plug->name, thisplugin))) | || strcasecmp(ptr->plug->name, thisplugin))) | |||
continue; | continue; | |||
found=1; | total_plugins++; | |||
if (ptr->plug->auxprop_store) | if (ptr->plug->auxprop_store) { | |||
ret = ptr->plug->auxprop_store(ptr->plug->glob_context, | ret = ptr->plug->auxprop_store(ptr->plug->glob_context, | |||
sparams, ctx, user, userl en); | sparams, ctx, user, userl en); | |||
if (ret == SASL_CONSTRAINT_VIOLAT) { | ||||
ret = SASL_OK; | ||||
num_constraint_violations++; | ||||
} | ||||
} | ||||
} | } | |||
if(last) break; | if(last) break; | |||
thisplugin = p+1; | thisplugin = p+1; | |||
} | } | |||
sasl_FREE(freeptr); | sasl_FREE(freeptr); | |||
} | } | |||
if(!found) { | if(total_plugins == 0) { | |||
_sasl_log(NULL, SASL_LOG_ERR, | _sasl_log(NULL, SASL_LOG_ERR, | |||
"could not find auxprop plugin, was searching for %s", | "could not find auxprop plugin, was searching for %s", | |||
plist ? plist : "[all]"); | plist ? plist : "[all]"); | |||
return SASL_FAIL; | return SASL_FAIL; | |||
} else if (total_plugins == num_constraint_violations) { | ||||
ret = SASL_CONSTRAINT_VIOLAT; | ||||
} | } | |||
return ret; | return ret; | |||
} | } | |||
/* It would be nice if we can show other information like Author, Company, Year, plugin version */ | /* It would be nice if we can show other information like Author, Company, Year, plugin version */ | |||
static void | static void | |||
_sasl_print_mechanism ( | _sasl_print_mechanism (sasl_auxprop_plug_t *m, | |||
sasl_auxprop_plug_t *m, | sasl_info_callback_stage_t stage, | |||
sasl_info_callback_stage_t stage, | void *rock __attribute__((unused)) | |||
void *rock | ||||
) | ) | |||
{ | { | |||
char delimiter; | ||||
if (stage == SASL_INFO_LIST_START) { | if (stage == SASL_INFO_LIST_START) { | |||
printf ("List of auxprop plugins follows\n"); | printf ("List of auxprop plugins follows\n"); | |||
return; | return; | |||
} else if (stage == SASL_INFO_LIST_END) { | } else if (stage == SASL_INFO_LIST_END) { | |||
return; | return; | |||
} | } | |||
/* Process the mechanism */ | /* Process the mechanism */ | |||
printf ("Plugin \"%s\" ", m->name); | printf ("Plugin \"%s\" ", m->name); | |||
End of changes. 26 change blocks. | ||||
20 lines changed or deleted | 99 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/ |