| /* ----------------------------------------------------------------------- * |
| * |
| * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
| * Boston MA 02110-1301, USA; either version 2 of the License, or |
| * (at your option) any later version; incorporated herein by reference. |
| * |
| * ----------------------------------------------------------------------- */ |
| |
| #include <string.h> |
| #include <xcrypt.h> |
| #include <sha1.h> |
| #include <base64.h> |
| |
| #include "menu.h" |
| |
| static int passwd_compare_sha1(const char *passwd, const char *entry) |
| { |
| struct { |
| SHA1_CTX ctx; |
| unsigned char sha1[20], pwdsha1[20]; |
| } d; |
| const char *p; |
| int rv; |
| |
| SHA1Init(&d.ctx); |
| |
| if ((p = strchr(passwd + 3, '$'))) { |
| SHA1Update(&d.ctx, (void *)passwd + 3, p - (passwd + 3)); |
| p++; |
| } else { |
| p = passwd + 3; /* Assume no salt */ |
| } |
| |
| SHA1Update(&d.ctx, (void *)entry, strlen(entry)); |
| SHA1Final(d.sha1, &d.ctx); |
| |
| memset(d.pwdsha1, 0, 20); |
| unbase64(d.pwdsha1, 20, p); |
| |
| rv = !memcmp(d.sha1, d.pwdsha1, 20); |
| |
| memset(&d, 0, sizeof d); |
| return rv; |
| } |
| |
| static int passwd_compare_md5(const char *passwd, const char *entry) |
| { |
| const char *crypted = crypt_md5(entry, passwd + 3); |
| int len = strlen(crypted); |
| |
| return !strncmp(crypted, passwd, len) && |
| (passwd[len] == '\0' || passwd[len] == '$'); |
| } |
| |
| static int passwd_compare_sha256(const char *passwd, const char *entry) |
| { |
| const char *crypted = sha256_crypt(entry, passwd + 3); |
| int len = strlen(crypted); |
| |
| return !strncmp(crypted, passwd, len) && |
| (passwd[len] == '\0' || passwd[len] == '$'); |
| } |
| |
| static int passwd_compare_sha512(const char *passwd, const char *entry) |
| { |
| const char *crypted = sha512_crypt(entry, passwd + 3); |
| int len = strlen(crypted); |
| |
| return !strncmp(crypted, passwd, len) && |
| (passwd[len] == '\0' || passwd[len] == '$'); |
| } |
| |
| int passwd_compare(const char *passwd, const char *entry) |
| { |
| if (passwd[0] != '$' || !passwd[1] || passwd[2] != '$') { |
| /* Plaintext passwd, yuck! */ |
| return !strcmp(entry, passwd); |
| } else { |
| switch (passwd[1]) { |
| case '1': |
| return passwd_compare_md5(passwd, entry); |
| case '4': |
| return passwd_compare_sha1(passwd, entry); |
| case '5': |
| return passwd_compare_sha256(passwd, entry); |
| case '6': |
| return passwd_compare_sha512(passwd, entry); |
| default: |
| return 0; /* Unknown encryption algorithm -> false */ |
| } |
| } |
| } |