|
gsasl
1.8.0
|
00001 /* mechtools.c --- Helper functions available for use by any mechanism. 00002 * Copyright (C) 2010-2012 Simon Josefsson 00003 * 00004 * This file is part of GNU SASL Library. 00005 * 00006 * GNU SASL Library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public License 00008 * as published by the Free Software Foundation; either version 2.1 of 00009 * the License, or (at your option) any later version. 00010 * 00011 * GNU SASL Library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with GNU SASL Library; if not, write to the Free 00018 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 */ 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include "config.h" 00025 #endif 00026 00027 /* Get specification. */ 00028 #include "mechtools.h" 00029 00030 /* Get strcmp. */ 00031 #include <string.h> 00032 00033 /* Get malloc, free. */ 00034 #include <stdlib.h> 00035 00036 /* Get asprintf. */ 00037 #include <stdio.h> 00038 00039 /* Get error codes. */ 00040 #include <gsasl.h> 00041 00042 /* Create in AUTHZID a newly allocated copy of STR where =2C is 00043 replaced with , and =3D is replaced with =. Return GSASL_OK on 00044 success, GSASL_MALLOC_ERROR on memory errors, GSASL_PARSE_ERRORS if 00045 string contains any unencoded ',' or incorrectly encoded 00046 sequence. */ 00047 static int 00048 unescape_authzid (const char *str, size_t len, char **authzid) 00049 { 00050 char *p; 00051 00052 if (memchr (str, ',', len) != NULL) 00053 return GSASL_MECHANISM_PARSE_ERROR; 00054 00055 p = *authzid = malloc (len + 1); 00056 if (!p) 00057 return GSASL_MALLOC_ERROR; 00058 00059 while (len > 0 && *str) 00060 { 00061 if (len >= 3 && str[0] == '=' && str[1] == '2' && str[2] == 'C') 00062 { 00063 *p++ = ','; 00064 str += 3; 00065 len -= 3; 00066 } 00067 else if (len >= 3 && str[0] == '=' && str[1] == '3' && str[2] == 'D') 00068 { 00069 *p++ = '='; 00070 str += 3; 00071 len -= 3; 00072 } 00073 else if (str[0] == '=') 00074 { 00075 free (*authzid); 00076 *authzid = NULL; 00077 return GSASL_MECHANISM_PARSE_ERROR; 00078 } 00079 else 00080 { 00081 *p++ = *str; 00082 str++; 00083 len--; 00084 } 00085 } 00086 *p = '\0'; 00087 00088 return GSASL_OK; 00089 } 00090 00091 /* Parse the GS2 header containing flags and authorization identity. 00092 Put authorization identity (or NULL) in AUTHZID and length of 00093 header in HEADERLEN. Return GSASL_OK on success or an error 00094 code.*/ 00095 int 00096 _gsasl_parse_gs2_header (const char *data, size_t len, 00097 char **authzid, size_t * headerlen) 00098 { 00099 char *authzid_endptr; 00100 00101 if (len < 3) 00102 return GSASL_MECHANISM_PARSE_ERROR; 00103 00104 if (strncmp (data, "n,,", 3) == 0) 00105 { 00106 *headerlen = 3; 00107 *authzid = NULL; 00108 } 00109 else if (strncmp (data, "n,a=", 4) == 0 && 00110 (authzid_endptr = memchr (data + 4, ',', len - 4))) 00111 { 00112 int res; 00113 00114 if (authzid_endptr == NULL) 00115 return GSASL_MECHANISM_PARSE_ERROR; 00116 00117 res = unescape_authzid (data + 4, authzid_endptr - (data + 4), authzid); 00118 if (res != GSASL_OK) 00119 return res; 00120 00121 *headerlen = authzid_endptr - data + 1; 00122 } 00123 else 00124 return GSASL_MECHANISM_PARSE_ERROR; 00125 00126 return GSASL_OK; 00127 } 00128 00129 /* Return newly allocated copy of STR with all occurrences of ',' 00130 replaced with =2C and '=' with '=3D', or return NULL on memory 00131 allocation errors. */ 00132 static char * 00133 escape_authzid (const char *str) 00134 { 00135 char *out = malloc (strlen (str) * 3 + 1); 00136 char *p = out; 00137 00138 if (!out) 00139 return NULL; 00140 00141 while (*str) 00142 { 00143 if (*str == ',') 00144 { 00145 memcpy (p, "=2C", 3); 00146 p += 3; 00147 } 00148 else if (*str == '=') 00149 { 00150 memcpy (p, "=3D", 3); 00151 p += 3; 00152 } 00153 else 00154 { 00155 *p = *str; 00156 p++; 00157 } 00158 str++; 00159 } 00160 *p = '\0'; 00161 00162 return out; 00163 } 00164 00165 /* Generate a newly allocated GS2 header, escaping authzid 00166 appropriately, and appending EXTRA. */ 00167 int 00168 _gsasl_gs2_generate_header (bool nonstd, char cbflag, 00169 const char *cbname, const char *authzid, 00170 size_t extralen, const char *extra, 00171 char **gs2h, size_t * gs2hlen) 00172 { 00173 int elen = extralen; 00174 char *gs2cbflag; 00175 int len; 00176 00177 if (cbflag == 'p') 00178 len = asprintf (&gs2cbflag, "p=%s", cbname); 00179 else if (cbflag == 'n') 00180 len = asprintf (&gs2cbflag, "n"); 00181 else if (cbflag == 'y') 00182 len = asprintf (&gs2cbflag, "y"); 00183 else 00184 /* internal caller error */ 00185 return GSASL_MECHANISM_PARSE_ERROR; 00186 00187 if (len <= 0 || gs2cbflag == NULL) 00188 return GSASL_MALLOC_ERROR; 00189 00190 if (authzid) 00191 { 00192 char *escaped_authzid = escape_authzid (authzid); 00193 00194 if (!escaped_authzid) 00195 { 00196 free (gs2cbflag); 00197 return GSASL_MALLOC_ERROR; 00198 } 00199 00200 len = asprintf (gs2h, "%s%s,a=%s,%.*s", nonstd ? "F," : "", 00201 gs2cbflag, escaped_authzid, elen, extra); 00202 00203 free (escaped_authzid); 00204 } 00205 else 00206 len = asprintf (gs2h, "%s%s,,%.*s", nonstd ? "F," : "", gs2cbflag, 00207 elen, extra); 00208 00209 free (gs2cbflag); 00210 00211 if (len <= 0 || gs2h == NULL) 00212 return GSASL_MALLOC_ERROR; 00213 00214 *gs2hlen = len; 00215 00216 return GSASL_OK; 00217 }
1.7.6.1