Home | History | Annotate | Download | only in menu
      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