-: 0:Source:ccselect_k5identity.c -: 0:Graph:/var/tsitkova/Sources/v10/trunk/src/lib/krb5/ccache/ccselect_k5identity.so.gcno -: 0:Data:/var/tsitkova/Sources/v10/trunk/src/lib/krb5/ccache/ccselect_k5identity.so.gcda -: 0:Runs:1602 -: 0:Programs:1 -: 1:/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -: 2:/* lib/krb5/ccache/ccselect_k5identity.c - k5identity ccselect module */ -: 3:/* -: 4: * Copyright (C) 2011 by the Massachusetts Institute of Technology. -: 5: * All rights reserved. -: 6: * -: 7: * Export of this software from the United States of America may -: 8: * require a specific license from the United States Government. -: 9: * It is the responsibility of any person or organization contemplating -: 10: * export to obtain such a license before exporting. -: 11: * -: 12: * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and -: 13: * distribute this software and its documentation for any purpose and -: 14: * without fee is hereby granted, provided that the above copyright -: 15: * notice appear in all copies and that both that copyright notice and -: 16: * this permission notice appear in supporting documentation, and that -: 17: * the name of M.I.T. not be used in advertising or publicity pertaining -: 18: * to distribution of the software without specific, written prior -: 19: * permission. Furthermore if you modify this software you must label -: 20: * your software as modified software and not distribute it in such a -: 21: * fashion that it might be confused with the original M.I.T. software. -: 22: * M.I.T. makes no representations about the suitability of -: 23: * this software for any purpose. It is provided "as is" without express -: 24: * or implied warranty. -: 25: */ -: 26: -: 27:#include "k5-int.h" -: 28:#include "cc-int.h" -: 29:#include -: 30:#include -: 31: -: 32:#ifndef _WIN32 -: 33: -: 34:#include -: 35: -: 36:static krb5_error_code 75: 37:k5identity_init(krb5_context context, krb5_ccselect_moddata *data_out, -: 38: int *priority_out) -: 39:{ 75: 40: *data_out = NULL; 75: 41: *priority_out = KRB5_CCSELECT_PRIORITY_AUTHORITATIVE; 75: 42: return 0; -: 43:} -: 44: -: 45:/* Match data (folded to lowercase if fold_case is set) against pattern. */ -: 46:static krb5_boolean 8: 47:fnmatch_data(const char *pattern, krb5_data *data, krb5_boolean fold_case) -: 48:{ -: 49: char *str, *p; -: 50: int res; -: 51: 8: 52: str = malloc(data->length + 1); 8: 53: if (str == NULL) #####: 54: return FALSE; 8: 55: memcpy(str, data->data, data->length); 8: 56: str[data->length] = '\0'; -: 57: 8: 58: if (fold_case) { 30: 59: for (p = str; *p != '\0'; p++) { 29: 60: if (isupper((unsigned char)*p)) #####: 61: *p = tolower((unsigned char)*p); -: 62: } -: 63: } -: 64: 8: 65: res = fnmatch(pattern, str, 0); 8: 66: free(str); 8: 67: return (res == 0); -: 68:} -: 69: -: 70:/* Return true if server satisfies the constraint given by name and value. */ -: 71:static krb5_boolean 10: 72:check_constraint(krb5_context context, const char *name, const char *value, -: 73: krb5_principal server) -: 74:{ 10: 75: if (strcmp(name, "realm") == 0) { 4: 76: return fnmatch_data(value, &server->realm, FALSE); 6: 77: } else if (strcmp(name, "service") == 0) { 8: 78: return (server->type == KRB5_NT_SRV_HST && server->length >= 2 && 3: 79: fnmatch_data(value, &server->data[0], FALSE)); 1: 80: } else if (strcmp(name, "host") == 0) { 2: 81: return (server->type == KRB5_NT_SRV_HST && server->length >= 2 && 1: 82: fnmatch_data(value, &server->data[1], TRUE)); -: 83: } -: 84: /* Assume unrecognized constraints are critical. */ #####: 85: return FALSE; -: 86:} -: 87: -: 88:/* -: 89: * If line begins with a valid principal and server matches the constraints -: 90: * listed afterwards, set *princ_out to the client principal described in line -: 91: * and return true. Otherwise return false. May destructively affect line. -: 92: */ -: 93:static krb5_boolean 9: 94:parse_line(krb5_context context, char *line, krb5_principal server, -: 95: krb5_principal *princ_out) -: 96:{ 9: 97: const char *whitespace = " \t\r\n"; -: 98: char *princ, *princ_end, *field, *field_end, *sep; -: 99: 9: 100: *princ_out = NULL; -: 101: -: 102: /* Find the bounds of the principal. */ 9: 103: princ = line + strspn(line, whitespace); 9: 104: if (*princ == '#') #####: 105: return FALSE; 9: 106: princ_end = princ + strcspn(princ, whitespace); 9: 107: if (princ_end == princ) #####: 108: return FALSE; -: 109: -: 110: /* Check all constraints. */ 9: 111: field = princ_end + strspn(princ_end, whitespace); 22: 112: while (*field != '\0') { 10: 113: field_end = field + strcspn(field, whitespace); 10: 114: if (*field_end != '\0') 8: 115: *field_end++ = '\0'; 10: 116: sep = strchr(field, '='); 10: 117: if (sep == NULL) /* Malformed line. */ #####: 118: return FALSE; 10: 119: *sep = '\0'; 10: 120: if (!check_constraint(context, field, sep + 1, server)) 6: 121: return FALSE; 4: 122: field = field_end + strspn(field_end, whitespace); -: 123: } -: 124: 3: 125: *princ_end = '\0'; 3: 126: return (krb5_parse_name(context, princ, princ_out) == 0); -: 127:} -: 128: -: 129:/* Determine the current user's homedir. Allow HOME to override the result for -: 130: * non-secure profiles; otherwise, use the euid's homedir from passwd. */ -: 131:static char * 129: 132:get_homedir(krb5_context context) -: 133:{ 129: 134: const char *homedir = NULL; -: 135: char pwbuf[BUFSIZ]; -: 136: struct passwd pwx, *pwd; -: 137: 129: 138: if (!context->profile_secure) 129: 139: homedir = getenv("HOME"); -: 140: 129: 141: if (homedir == NULL) { #####: 142: if (k5_getpwuid_r(geteuid(), &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0) #####: 143: return NULL; #####: 144: homedir = pwd->pw_dir; -: 145: } -: 146: 129: 147: return strdup(homedir); -: 148:} -: 149: -: 150:static krb5_error_code 129: 151:k5identity_choose(krb5_context context, krb5_ccselect_moddata data, -: 152: krb5_principal server, krb5_ccache *cache_out, -: 153: krb5_principal *princ_out) -: 154:{ -: 155: krb5_error_code ret; 129: 156: krb5_principal princ = NULL; -: 157: char *filename, *homedir; -: 158: FILE *fp; -: 159: char buf[256]; -: 160: 129: 161: *cache_out = NULL; 129: 162: *princ_out = NULL; -: 163: -: 164: /* Open the .k5identity file. */ 129: 165: homedir = get_homedir(context); 129: 166: if (homedir == NULL) #####: 167: return KRB5_PLUGIN_NO_HANDLE; 129: 168: ret = k5_path_join(homedir, ".k5identity", &filename); 129: 169: free(homedir); 129: 170: if (ret) #####: 171: return ret; 129: 172: fp = fopen(filename, "r"); 129: 173: free(filename); 129: 174: if (fp == NULL) 125: 175: return KRB5_PLUGIN_NO_HANDLE; -: 176: -: 177: /* Look for a line with constraints matched by server. */ 14: 178: while (fgets(buf, sizeof(buf), fp) != NULL) { 9: 179: if (parse_line(context, buf, server, &princ)) 3: 180: break; -: 181: } 4: 182: fclose(fp); 4: 183: if (princ == NULL) 1: 184: return KRB5_PLUGIN_NO_HANDLE; -: 185: -: 186: /* Look for a ccache with the appropriate client principal. If we don't -: 187: * find out, set *princ_out to indicate the desired client principal. */ 3: 188: ret = krb5_cc_cache_match(context, princ, cache_out); 6: 189: if (ret == 0 || ret == KRB5_CC_NOTFOUND) 3: 190: *princ_out = princ; -: 191: else #####: 192: krb5_free_principal(context, princ); 3: 193: return ret; -: 194:} -: 195: -: 196:krb5_error_code 75: 197:ccselect_k5identity_initvt(krb5_context context, int maj_ver, int min_ver, -: 198: krb5_plugin_vtable vtable) -: 199:{ -: 200: krb5_ccselect_vtable vt; -: 201: 75: 202: if (maj_ver != 1) #####: 203: return KRB5_PLUGIN_VER_NOTSUPP; 75: 204: vt = (krb5_ccselect_vtable)vtable; 75: 205: vt->name = "k5identity"; 75: 206: vt->init = k5identity_init; 75: 207: vt->choose = k5identity_choose; 75: 208: return 0; -: 209:} -: 210: -: 211:#endif /* not _WIN32 */