Limit password length to 64 characters
[blerg.git] / common / auth.c
1 /* Blerg is (C) 2011 The Dominion of Awesome, and is distributed under a
2  * BSD-style license.  Please see the COPYING file for details.
3  */
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "config.h"
11 #include "auth.h"
12 #include "util.h"
13
14 #define TOKEN_SIZE 16
15 #define MAX_PASSWORD_LENGTH 64
16
17 int auth_set_password(const char *username, const char *password) {
18         char filename[512];
19         int fd, n;
20
21         if (!valid_name(username) || !blerg_exists(username))
22                 return 0;
23
24         n = strlen(password);
25         if (n > MAX_PASSWORD_LENGTH)
26                 return 0;
27
28         snprintf(filename, 512, "%s/%s/password", DATA_PATH, username);
29         fd = open(filename, O_WRONLY | O_CREAT, 0600);
30         write(fd, password, n);
31         close(fd);
32         
33         return 1;
34 }
35
36 int auth_get_password(const char *username, char *password) {
37         char filename[512];
38         int fd;
39         int len = 0;
40
41         if (!valid_name(username))
42                 return 0;
43
44         sprintf(filename, "%s/%s/password", DATA_PATH, username);
45         fd = open(filename, O_RDONLY);
46         if (fd == -1)
47                 return 0;
48         len = read(fd, password, MAX_PASSWORD_LENGTH);
49         close(fd);
50
51         password[len] = 0;
52
53         return 1;
54 }
55
56 int auth_check_password(const char *username, const char *password) {
57         char epw[33];
58
59         if (auth_get_password(username, epw) == 0)
60                 return 0;
61
62         if (strncmp(password, epw, MAX_PASSWORD_LENGTH) == 0)
63                 return 1;
64         else
65                 return 0;
66 }
67
68 void hexify(char *dst, char *src, int len) {
69         static char hex[] = "0123456789abcdef";
70         int i;
71
72         for (i = 0; i < len; i++) {
73                 dst[i * 2]     = hex[(src[i] & 0xF0) >> 4];
74                 dst[i * 2 + 1] = hex[src[i] & 0xF];
75         }
76 }
77
78 char *create_random_token() {
79         unsigned char buf[TOKEN_SIZE];
80         char *token;
81         int rand_fd;
82
83         rand_fd = open("/dev/urandom", O_RDONLY);
84         if (rand_fd == -1) {
85                 perror("Could not open /dev/urandom\n");
86                 return 0;
87         }
88         read(rand_fd, buf, TOKEN_SIZE);
89         close(rand_fd);
90
91         token = malloc(TOKEN_SIZE * 2 + 1);
92         hexify(token, buf, TOKEN_SIZE);
93         token[TOKEN_SIZE * 2] = 0;
94
95         return token;
96 }
97
98 int auth_login(const char *username, const char *password) {
99         char filename[512];
100         int token_fd;
101
102         if (!auth_check_password(username, password))
103                 return 0;
104
105         sprintf(filename, "%s/%s/token", DATA_PATH, username);
106         token_fd = open(filename, O_WRONLY | O_CREAT, 0600);
107         if (token_fd == -1) {
108                 perror("Could not open token");
109                 return 0;
110         }
111
112         char *token = create_random_token();
113         write(token_fd, token, TOKEN_SIZE * 2);
114         close(token_fd);
115         free(token);
116
117         return 1;
118 }
119
120 int auth_logout(const char *username) {
121         char filename[512];
122
123         if (!valid_name(username))
124                 return 0;
125
126         sprintf(filename, "%s/%s/token", DATA_PATH, username);
127         if (unlink(filename) == -1)
128                 return 0;
129
130         return 1;
131 }
132
133 char *auth_get_token(const char *username) {
134         char filename[512];
135         char *token;
136         int token_fd;
137
138         if (!valid_name(username))
139                 return 0;
140
141         sprintf(filename, "%s/%s/token", DATA_PATH, username);
142         token_fd = open(filename, O_RDONLY, 0600);
143         if (token_fd == -1) {
144                 perror("Could not open token");
145                 return NULL;
146         }
147
148         token = malloc(TOKEN_SIZE * 2 + 1);
149         read(token_fd, token, TOKEN_SIZE * 2);
150         close(token_fd);
151
152         return token;
153 }
154
155 int auth_check_token(const char *username, const char *given_token) {
156         char *token = auth_get_token(username);
157         if (token != NULL && given_token != NULL) {
158                 int ret = (strncmp(token, given_token, TOKEN_SIZE * 2) == 0);
159                 free(token);
160                 return ret;
161         } else {
162                 return 0;
163         }
164 }