Merge branch 'master' into for-erwan
[profile/ivi/syslinux.git] / com32 / menu / passwd.c
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 }