00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 # include "config.h"
00025 #endif
00026
00027
00028 #include "mechtools.h"
00029
00030
00031 #include <string.h>
00032
00033
00034 #include <stdlib.h>
00035
00036
00037 #include <stdio.h>
00038
00039
00040 #include <gsasl.h>
00041
00042
00043
00044
00045
00046
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
00092
00093
00094
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
00130
00131
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
00166
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
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 if (len <= 0 || gs2cbflag == NULL)
00210 {
00211 free (gs2cbflag);
00212 return GSASL_MALLOC_ERROR;
00213 }
00214
00215 *gs2hlen = len;
00216 }