1 /* $NetBSD: saslc.c,v 1.4 2011/02/12 23:21:32 christos 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 #include <sys/cdefs.h> 38 __RCSID("$NetBSD: saslc.c,v 1.4 2011/02/12 23:21:32 christos Exp $"); 39 40 #include <assert.h> 41 #include <ctype.h> 42 #include <saslc.h> 43 #include <stdbool.h> 44 #include <stdbool.h> 45 #include <stdio.h> 46 #include <string.h> 47 48 #include "crypto.h" /* XXX: for saslc_{de,en}code64() */ 49 #include "dict.h" 50 #include "error.h" 51 #include "mech.h" 52 #include "msg.h" 53 #include "parser.h" 54 #include "saslc_private.h" 55 56 /** 57 * @brief check for a valid application name (no path separator) 58 * @param appname application name 59 * @return true if application name is valid, false otherwise 60 */ 61 static bool 62 saslc__valid_appname(const char *appname) 63 { 64 const char *p; 65 66 for (p = appname; *p; p++) 67 if (*p == '/') 68 return false; 69 70 return true; 71 } 72 73 /** 74 * @brief allocates new saslc context 75 * @return pointer to the saslc context 76 */ 77 saslc_t * 78 saslc_alloc(void) 79 { 80 81 /* XXX: Check this as early as possible. */ 82 saslc_debug = getenv(SASLC_ENV_DEBUG) != NULL; 83 84 return calloc(1, sizeof(saslc_t)); 85 } 86 87 /** 88 * @brief initializes sasl context, basing on application name function 89 * parses configuration files, sets up default properties and creates 90 * mechanisms list for the context. 91 * @param ctx sasl context 92 * @param appname application name, NULL could be used for generic aplication 93 * @param pathname location of config files. if NULL, use environment or default 94 * @return 0 on success, -1 otherwise. 95 */ 96 int 97 saslc_init(saslc_t *ctx, const char *appname, const char *pathname) 98 { 99 100 /* ctx is already zeroed by saslc_alloc(). */ 101 ctx->prop = saslc__dict_create(); 102 103 if (appname != NULL) { 104 if (saslc__valid_appname(appname) == false) { 105 saslc__error_set(ERR(ctx), ERROR_BADARG, 106 "application name is not permited"); 107 goto error; 108 } 109 if ((ctx->appname = strdup(appname)) == NULL) { 110 saslc__error_set_errno(ERR(ctx), ERROR_NOMEM); 111 goto error; 112 } 113 } 114 if (pathname != NULL && *pathname != '\0') { 115 if ((ctx->pathname = strdup(pathname)) == NULL) { 116 saslc__error_set_errno(ERR(ctx), ERROR_NOMEM); 117 goto error; 118 } 119 } 120 ctx->mechanisms = saslc__mech_list_create(ctx); 121 if (ctx->mechanisms == NULL) 122 goto error; 123 124 /* load the global and mechanism dictionaries */ 125 if (saslc__parser_config(ctx) == -1) { 126 free(ctx->appname); 127 ctx->appname = NULL; 128 saslc__dict_destroy(ctx->prop); 129 ctx->prop = NULL; 130 saslc__mech_list_destroy(ctx->mechanisms); 131 ctx->mechanisms = NULL; 132 return -1; 133 } 134 return 0; 135 136 error: 137 if (ctx->pathname != NULL) { 138 free(ctx->pathname); 139 ctx->pathname = NULL; 140 } 141 if (ctx->appname != NULL) { 142 free(ctx->appname); 143 ctx->appname = NULL; 144 } 145 free(ctx->prop); 146 ctx->prop = NULL; 147 return -1; 148 } 149 150 /** 151 * @brief gets string message of last error. 152 * @param ctx context 153 * @return pointer to the error message. 154 */ 155 const char * 156 saslc_strerror(saslc_t *ctx) 157 { 158 159 return saslc__error_get_strerror(ERR(ctx)); 160 } 161 162 /** 163 * @brief destroys and deallocate resources used by the context. 164 * @param ctx context 165 * the context (if any) should be destroyed 166 * @return 0 on success, -1 on failure 167 */ 168 int 169 saslc_end(saslc_t *ctx) 170 { 171 172 if (ctx->refcnt > 0) { 173 saslc__error_set(ERR(ctx), ERROR_GENERAL, 174 "context has got assigned active sessions"); 175 return -1; 176 } 177 178 if (ctx->mechanisms != NULL) 179 saslc__mech_list_destroy(ctx->mechanisms); 180 181 if (ctx->prop != NULL) 182 saslc__dict_destroy(ctx->prop); 183 184 free(ctx->appname); 185 free(ctx); 186 return 0; 187 } 188