UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2013 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 33 #include <openssl/sha.h> 34 #if defined(__sun) && defined(__SunOS_5_10) 35 #include <sha2.h> 36 #define SHA256_Init SHA256Init 37 #define SHA256_Update SHA256Update 38 #define SHA256_Final SHA256Final 39 #endif 40 41 #include "../util/atomic.h" 42 #include "../util/util.h" 43 44 #include "keyfile_auth.h" 45 46 Keyfile* keyfile_new() { 47 Keyfile *keyfile = malloc(sizeof(Keyfile)); 48 keyfile->authdb.get_user = keyfile_get_user; 49 keyfile->authdb.use_cache = 0; 50 keyfile->users = ucx_map_new(16); 51 keyfile->ref = 1; 52 return keyfile; 53 } 54 55 void keyfile_ref(Keyfile *keyfile) { 56 ws_atomic_inc32(&keyfile->ref); 57 } 58 59 void keyfile_unref(Keyfile *keyfile) { 60 uint32_t ref = ws_atomic_dec32(&keyfile->ref); 61 if(ref == 0) { 62 UcxMapIterator i = ucx_map_iterator(keyfile->users); 63 KeyfileUser *user; 64 UCX_MAP_FOREACH(key, user, i) { 65 free(user->user.name); 66 free(user->hash); 67 for(int n=0;n<user->numgroups;n++) { 68 free(user->groups[n].ptr); 69 } 70 free(user->groups); 71 } 72 ucx_map_free(keyfile->users); 73 74 free(keyfile->authdb.name); 75 free(keyfile); 76 } 77 } 78 79 void keyfile_add_user( 80 Keyfile *keyfile, 81 sstr_t name, 82 enum KeyfileHashType hash_type, 83 sstr_t hash, 84 sstr_t *groups, 85 size_t ngroups) 86 { 87 if(hash.length < 12) { 88 // hash too short 89 // TODO: log 90 return; 91 } 92 93 KeyfileUser *user = malloc(sizeof(KeyfileUser)); 94 user->user.name = sstrdup(name).ptr; 95 user->user.uid = -1; 96 user->user.gid = -1; 97 user->user.verify_password = keyfile_user_verify_password; 98 user->user.check_group = keyfile_user_check_group; 99 user->user.free = keyfile_user_free; 100 101 user->hash_type = hash_type; 102 user->hash = malloc(hash.length + 1); 103 user->hashlen = util_base64decode(hash.ptr, hash.length, user->hash); 104 105 user->groups = calloc(ngroups, sizeof(sstr_t)); 106 for(int i=0;i<ngroups;i++) { 107 user->groups[i] = sstrdup(groups[i]); 108 } 109 110 // add to keyfile 111 ucx_map_sstr_put(keyfile->users, name, user); 112 } 113 114 // authdb functions 115 116 User* keyfile_get_user(AuthDB *db, char *user) { 117 Keyfile *keyfile = (Keyfile*)db; 118 return ucx_map_cstr_get(keyfile->users, user); 119 } 120 121 int keyfile_user_verify_password(User *user, char *password) { 122 KeyfileUser *usr = (KeyfileUser*)user; 123 return ssha_verify(usr, password); 124 } 125 126 int keyfile_user_check_group(User *user, char *group) { 127 KeyfileUser *usr = (KeyfileUser*)user; 128 sstr_t grp = sstr(group); 129 for(int i=0;i<usr->numgroups;i++) { 130 if(!sstrcmp(usr->groups[i], grp)) { 131 return 1; 132 } 133 } 134 return 0; 135 } 136 137 void keyfile_user_free(User *user) { 138 // don't free, it will be freed by keyfile_unref 139 } 140 141 142 int ssha_verify(KeyfileUser *user, char *password) { 143 /* 144 * SSHA: SHA(pw + salt) + salt 145 * user->hash is already base64 decoded 146 */ 147 148 size_t hlen; 149 switch(user->hash_type) { 150 case KEYFILE_SSHA: hlen = 20; break; 151 case KEYFILE_SSHA256: hlen = 32; break; 152 case KEYFILE_SSHA512: hlen = 64; break; 153 } 154 155 char *salt = user->hash + hlen; 156 size_t saltlen = user->hashlen - hlen; 157 158 size_t pwlen = strlen(password); 159 160 unsigned char pwhash[64]; 161 switch(user->hash_type) { 162 case KEYFILE_SSHA: { 163 SHA_CTX ctx; 164 SHA1_Init(&ctx); 165 SHA1_Update(&ctx, password, pwlen); 166 SHA1_Update(&ctx, salt, saltlen); 167 SHA1_Final(pwhash, &ctx); 168 break; 169 } 170 case KEYFILE_SSHA256: { 171 SHA256_CTX ctx; 172 SHA256_Init(&ctx); 173 SHA256_Update(&ctx, password, pwlen); 174 SHA256_Update(&ctx, salt, saltlen); 175 SHA256_Final(pwhash, &ctx); 176 break; 177 } 178 case KEYFILE_SSHA512: { 179 SHA512_CTX ctx; 180 SHA512_Init(&ctx); 181 SHA512_Update(&ctx, password, pwlen); 182 SHA512_Update(&ctx, salt, saltlen); 183 SHA512_Final(pwhash, &ctx); 184 break; 185 } 186 } 187 188 if(!memcmp(user->hash, pwhash, hlen)) { 189 return 1; 190 } else { 191 return 0; 192 } 193 } 194 195