1 /* $Id: saslc.c,v 1.2 2011/01/29 23:35:31 agc Exp $ */ 2 3 /* Copyright (c) 2010 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Mateusz Kocielski. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the NetBSD 20 * Foundation, Inc. and its contributors. 21 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #include <saslc.h> 39 #include <ctype.h> 40 #include <stdio.h> 41 #include <string.h> 42 #include <stdbool.h> 43 #include <assert.h> 44 #include "dict.h" 45 #include "parser.h" 46 #include "saslc_private.h" 47 #include "mech.h" 48 #include "error.h" 49 50 /* local headers */ 51 52 static bool saslc__valid_appname(const char *); 53 54 /** 55 * @brief checks if application name is valid 56 * @param appname application name 57 * @return true if application name is valid, false otherwise 58 */ 59 60 static bool 61 saslc__valid_appname(const char *appname) 62 { 63 const char *p; 64 65 for (p = appname; *p; p++) 66 if (!isalnum((unsigned char)*p)) 67 return false; 68 69 return true; 70 } 71 72 73 /** 74 * @brief allocates new saslc context 75 * @return saslc context 76 */ 77 78 saslc_t * 79 saslc_alloc(void) 80 { 81 return calloc(1, sizeof(saslc_t)); 82 } 83 84 /** 85 * @brief initializes sasl context, basing on application name function 86 * parses configuration files, sets up default peroperties and creates 87 * mechanisms list for the context. 88 * @param ctx sasl context 89 * @param appname application name, NULL could be used for generic aplication 90 * @return 0 on success, -1 otherwise. 91 */ 92 93 int 94 saslc_init(saslc_t *ctx, const char *appname) 95 { 96 memset(ctx, 0, sizeof(*ctx)); 97 98 LIST_INIT(&ctx->sessions); 99 100 ctx->prop = saslc__dict_create(); 101 102 if (ctx->prop == NULL) 103 return -1; 104 105 /* appname */ 106 if (appname != NULL) { 107 /* check if appname is valid */ 108 if (saslc__valid_appname(appname) == false) { 109 saslc__error_set(ERR(ctx), ERROR_BADARG, 110 "application name is not permited"); 111 goto error; 112 } 113 114 ctx->appname = strdup(appname); 115 if (ctx->appname == NULL) { 116 saslc__error_set_errno(ERR(ctx), ERROR_NOMEM); 117 goto error; 118 } 119 } else 120 ctx->appname = NULL; 121 122 /* mechanisms list */ 123 if (saslc__mech_list_create(ctx) == -1) 124 goto error; 125 126 /* parse configuration files */ 127 if (saslc__parser_config(ctx) == -1) 128 /* errno is set up by parser */ 129 goto error; 130 131 return 0; 132 133 error: 134 if (ctx->appname != NULL) 135 free((void *)ctx->appname); 136 if (ctx->prop != NULL) 137 saslc__dict_destroy(ctx->prop); 138 139 ctx->appname = NULL; 140 ctx->prop = NULL; 141 142 return -1; 143 } 144 145 /** 146 * @brief gets string message of last error. 147 * @param ctx context 148 * @return error string 149 */ 150 151 const char * 152 saslc_strerror(saslc_t *ctx) 153 { 154 return saslc__error_get_strerror(ERR(ctx)); 155 } 156 157 /** 158 * @brief destroys and deallocate resources used by the context. 159 * @param ctx context 160 * @param destroy_sessions indicates if all existing sessions assigned to 161 * the context (if any) should be destroyed 162 * @return 0 on success, -1 on failure 163 */ 164 165 int 166 saslc_end(saslc_t *ctx, bool destroy_sessions) 167 { 168 /* check if there're any assigned sessions */ 169 if (!LIST_EMPTY(&ctx->sessions) && destroy_sessions == false) { 170 saslc__error_set(ERR(ctx), ERROR_GENERAL, 171 "context has got assigned active sessions"); 172 return -1; 173 } 174 175 /* destroy all assigned sessions (note that if any nodes are assigned, 176 * then destroy_sessions == true) */ 177 assert(LIST_EMPTY(&ctx->sessions) || destroy_sessions == true); 178 while (!LIST_EMPTY(&ctx->sessions)) 179 saslc_sess_end(LIST_FIRST(&ctx->sessions)); 180 181 /* mechanism list */ 182 if (!LIST_EMPTY(&ctx->mechanisms)) 183 saslc__mech_list_destroy(&ctx->mechanisms); 184 185 /* properties */ 186 if (ctx->prop != NULL) 187 saslc__dict_destroy(ctx->prop); 188 189 /* application name */ 190 free(ctx->appname); 191 192 /* free context */ 193 free(ctx); 194 195 return 0; 196 } 197