/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ /**@CFILE auth_common.c * * Functions common to both client and server authentication. * * @author Pekka Pessi * * @date Original Created: Thu Feb 22 12:10:37 2001 ppessi * @date Created: Wed May 17 13:37:50 EEST 2006 ppessi */ #include "config.h" #include "sofia-sip/auth_common.h" #include "sofia-sip/msg_header.h" #include #include #include #include #if !HAVE_STRCASESTR char *strcasestr(char const *haystack, char const *needle); #endif su_inline int has_token(char const *qstring, char const *token); /** * Parse authentication parameters. * * The function auth_get_params() searches for the authentication parameters * in @a params. The parameter list @a params is seached for each parameter * given in in vararg section, and if it is found, its value is assigned to * the given address. * * @note The field name should contain the equal ("=") sign. * * @return * The function auth_get_params() returns number of parameters found in * params, or -1 upon an error. */ issize_t auth_get_params(su_home_t *home, char const * const params[], ... /* char const *fmt, char const **return_value */) { int n, j; size_t len, namelen; char const *fmt, *expected; char const *value, *p, **return_value; va_list(ap); assert(params); if (!params) return -1; va_start(ap, params); for (n = 0; (fmt = va_arg(ap, char const *));) { return_value = va_arg(ap, char const **); len = strlen(fmt); if (!len) continue; namelen = strcspn(fmt, "="); expected = fmt + namelen + 1; value = NULL; if (expected[0]) { /* value match: format is name=expected, if expected is found in parameter value, return non-NULL pointer in *return_value */ for (j = 0; (p = params[j++]);) { if (strcasecmp(p, fmt) == 0) { /* Matched the whole parameter with fmt name=expected */ value = p; break; } else if (strncasecmp(p, fmt, namelen) || p[namelen] != '=') continue; p = p + namelen + 1; if (p[0] == '"' && has_token(p, expected)) { /* Quoted parameter value has expected value, * e.g., qop=auth matches qop="auth,auth-int" */ value = p; break; } else if (strcasecmp(p, expected) == 0) { /* Parameter value matches with extected value * e.g., qop=auth matches qop=auth */ value = p; break; } } } else { /* format is name= , return unquoted parameter value after = */ for (j = 0; (p = params[j++]);) { if (strncasecmp(p, fmt, len)) continue; if (p[len] == '"') value = msg_unquote_dup(home, p + len); else value = su_strdup(home, p + len); if (value == NULL) return -1; break; } } if (value) { *return_value = value; n++; } } va_end(ap); return n; } int auth_struct_copy(void *dst, void const *src, isize_t s_size) { int d_size = *(int *)dst; if (d_size < 0) return -1; if ((size_t)d_size > s_size) { memcpy(dst, src, s_size); memset((char *)dst + s_size, 0, d_size - s_size); } else { memcpy(dst, src, d_size); *(int *)dst = d_size; } return 0; } su_inline int has_token(char const *qstring, char const *token) { size_t n = strlen(token); char const *q; q = strcasestr(qstring, token); return (q && (q[n] == 0 || strchr("\", \t", q[n])) && (q == qstring || strchr("\", \t", q[-1]))); } /** Compare two strings, even if they are quoted */ int auth_strcmp(char const *quoted, char const *unquoted) { size_t i, j; if (quoted[0] != '"') return strcmp(quoted, unquoted); /* Compare quoted with unquoted */ for (i = 1, j = 0; ; i++, j++) { char q = quoted[i], u = unquoted[j]; if (q == '"') q = '\0'; else if (q == '\\' && u != '\0') q = quoted[i++]; if (q - u) return q - u; if (q == '\0') return 0; } }