1 /* ----------------------------------------------------------------------- * 2 * 3 * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 8 * Boston MA 02110-1301, USA; either version 2 of the License, or 9 * (at your option) any later version; incorporated herein by reference. 10 * 11 * ----------------------------------------------------------------------- */ 12 13 #include <string.h> 14 #include <xcrypt.h> 15 #include <sha1.h> 16 #include <base64.h> 17 18 #include "menu.h" 19 20 static int passwd_compare_sha1(const char *passwd, const char *entry) 21 { 22 struct { 23 SHA1_CTX ctx; 24 unsigned char sha1[20], pwdsha1[20]; 25 } d; 26 const char *p; 27 int rv; 28 29 SHA1Init(&d.ctx); 30 31 if ((p = strchr(passwd + 3, '$'))) { 32 SHA1Update(&d.ctx, (void *)passwd + 3, p - (passwd + 3)); 33 p++; 34 } else { 35 p = passwd + 3; /* Assume no salt */ 36 } 37 38 SHA1Update(&d.ctx, (void *)entry, strlen(entry)); 39 SHA1Final(d.sha1, &d.ctx); 40 41 memset(d.pwdsha1, 0, 20); 42 unbase64(d.pwdsha1, 20, p); 43 44 rv = !memcmp(d.sha1, d.pwdsha1, 20); 45 46 memset(&d, 0, sizeof d); 47 return rv; 48 } 49 50 static int passwd_compare_md5(const char *passwd, const char *entry) 51 { 52 const char *crypted = crypt_md5(entry, passwd + 3); 53 int len = strlen(crypted); 54 55 return !strncmp(crypted, passwd, len) && 56 (passwd[len] == '\0' || passwd[len] == '$'); 57 } 58 59 static int passwd_compare_sha256(const char *passwd, const char *entry) 60 { 61 const char *crypted = sha256_crypt(entry, passwd + 3); 62 int len = strlen(crypted); 63 64 return !strncmp(crypted, passwd, len) && 65 (passwd[len] == '\0' || passwd[len] == '$'); 66 } 67 68 static int passwd_compare_sha512(const char *passwd, const char *entry) 69 { 70 const char *crypted = sha512_crypt(entry, passwd + 3); 71 int len = strlen(crypted); 72 73 return !strncmp(crypted, passwd, len) && 74 (passwd[len] == '\0' || passwd[len] == '$'); 75 } 76 77 int passwd_compare(const char *passwd, const char *entry) 78 { 79 if (passwd[0] != '$' || !passwd[1] || passwd[2] != '$') { 80 /* Plaintext passwd, yuck! */ 81 return !strcmp(entry, passwd); 82 } else { 83 switch (passwd[1]) { 84 case '1': 85 return passwd_compare_md5(passwd, entry); 86 case '4': 87 return passwd_compare_sha1(passwd, entry); 88 case '5': 89 return passwd_compare_sha256(passwd, entry); 90 case '6': 91 return passwd_compare_sha512(passwd, entry); 92 default: 93 return 0; /* Unknown encryption algorithm -> false */ 94 } 95 } 96 } 97