diff options
| -rw-r--r-- | RELEASE_NOTES.md | 2 | ||||
| -rw-r--r-- | data.c | 2 | ||||
| -rw-r--r-- | doc/snac.1 | 6 | ||||
| -rw-r--r-- | main.c | 17 | ||||
| -rw-r--r-- | snac.c | 6 | ||||
| -rw-r--r-- | snac.h | 11 | ||||
| -rw-r--r-- | utils.c | 55 |
7 files changed, 67 insertions, 32 deletions
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e79bf2a..f713cb9 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | 2 | ||
| 3 | ## 2.14 | 3 | ## 2.14 |
| 4 | 4 | ||
| 5 | New command-line operation, `resetpwd`, to reset a user's password to a new, random one. | ||
| 6 | |||
| 5 | Added a user setup option to toggle if sensitive content is shown or not by default (contributed by kensanata). | 7 | Added a user setup option to toggle if sensitive content is shown or not by default (contributed by kensanata). |
| 6 | 8 | ||
| 7 | Fixed crash when debug level >= 2 (contributed by kensanata). | 9 | Fixed crash when debug level >= 2 (contributed by kensanata). |
| @@ -120,7 +120,7 @@ void user_free(snac *snac) | |||
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | 122 | ||
| 123 | int user_open(snac *snac, char *uid) | 123 | int user_open(snac *snac, const char *uid) |
| 124 | /* opens a user */ | 124 | /* opens a user */ |
| 125 | { | 125 | { |
| 126 | int ret = 0; | 126 | int ret = 0; |
| @@ -150,6 +150,8 @@ Upgrades the data storage after installing a new version. | |||
| 150 | Only necessary if | 150 | Only necessary if |
| 151 | .Nm | 151 | .Nm |
| 152 | complains and demands it. | 152 | complains and demands it. |
| 153 | .It Cm httpd Ar basedir | ||
| 154 | Starts the daemon. | ||
| 153 | .It Cm purge Ar basedir | 155 | .It Cm purge Ar basedir |
| 154 | Purges old data from the timeline of all users. | 156 | Purges old data from the timeline of all users. |
| 155 | .It Cm adduser Ar basedir Op uid | 157 | .It Cm adduser Ar basedir Op uid |
| @@ -160,8 +162,8 @@ the server | |||
| 160 | is installed in the user's | 162 | is installed in the user's |
| 161 | .Pa static/ | 163 | .Pa static/ |
| 162 | directory. | 164 | directory. |
| 163 | .It Cm httpd Ar basedir | 165 | .It Cm resetpwd Ar basedir Ar uid |
| 164 | Starts the daemon. | 166 | Resets a user's password to a new, random one. |
| 165 | .It Cm queue Ar basedir Ar uid | 167 | .It Cm queue Ar basedir Ar uid |
| 166 | Processes the output queue of the specied user, sending all | 168 | Processes the output queue of the specied user, sending all |
| 167 | enqueued messages and re-enqueing the failing ones. This command | 169 | enqueued messages and re-enqueing the failing ones. This command |
| @@ -24,21 +24,10 @@ int usage(void) | |||
| 24 | printf("queue {basedir} {uid} Processes a user queue\n"); | 24 | printf("queue {basedir} {uid} Processes a user queue\n"); |
| 25 | printf("follow {basedir} {uid} {actor} Follows an actor\n"); | 25 | printf("follow {basedir} {uid} {actor} Follows an actor\n"); |
| 26 | printf("unfollow {basedir} {uid} {actor} Unfollows an actor\n"); | 26 | printf("unfollow {basedir} {uid} {actor} Unfollows an actor\n"); |
| 27 | |||
| 28 | // printf("check {basedir} [{uid}] Checks the database\n"); | ||
| 29 | |||
| 30 | // printf("update {basedir} {uid} Sends a user update to followers\n"); | ||
| 31 | // printf("passwd {basedir} {uid} Sets the password for {uid}\n"); | ||
| 32 | // printf("unfollow {basedir} {uid} {actor} Unfollows an actor\n"); | ||
| 33 | // printf("mute {basedir} {uid} {actor} Mutes an actor\n"); | ||
| 34 | // printf("unmute {basedir} {uid} {actor} Unmutes an actor\n"); | ||
| 35 | // printf("like {basedir} {uid} {url} Likes an url\n"); | ||
| 36 | // printf("announce {basedir} {uid} {url} Announces (boosts) an url\n"); | ||
| 37 | // printf("note {basedir} {uid} {'text'} Sends a note to followers\n"); | ||
| 38 | |||
| 39 | printf("request {basedir} {uid} {url} Requests an object\n"); | 27 | printf("request {basedir} {uid} {url} Requests an object\n"); |
| 40 | printf("actor {basedir} {uid} {url} Requests an actor\n"); | 28 | printf("actor {basedir} {uid} {url} Requests an actor\n"); |
| 41 | printf("note {basedir} {uid} {'text'} Sends a note to followers\n"); | 29 | printf("note {basedir} {uid} {'text'} Sends a note to followers\n"); |
| 30 | printf("resetpwd {basedir} {uid} Resets the password of a user\n"); | ||
| 42 | 31 | ||
| 43 | return 1; | 32 | return 1; |
| 44 | } | 33 | } |
| @@ -150,6 +139,10 @@ int main(int argc, char *argv[]) | |||
| 150 | return 1; | 139 | return 1; |
| 151 | } | 140 | } |
| 152 | 141 | ||
| 142 | if (strcmp(cmd, "resetpwd") == 0) { | ||
| 143 | return resetpwd(&snac); | ||
| 144 | } | ||
| 145 | |||
| 153 | if (strcmp(cmd, "queue") == 0) { | 146 | if (strcmp(cmd, "queue") == 0) { |
| 154 | process_queue(&snac); | 147 | process_queue(&snac); |
| 155 | return 0; | 148 | return 0; |
| @@ -57,7 +57,7 @@ double ftime(void) | |||
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | 59 | ||
| 60 | int validate_uid(char *uid) | 60 | int validate_uid(const char *uid) |
| 61 | /* returns if uid is a valid identifier */ | 61 | /* returns if uid is a valid identifier */ |
| 62 | { | 62 | { |
| 63 | while (*uid) { | 63 | while (*uid) { |
| @@ -103,7 +103,7 @@ void snac_debug(snac *snac, int level, d_char *str) | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | 105 | ||
| 106 | d_char *hash_password(char *uid, char *passwd, char *nonce) | 106 | d_char *hash_password(const char *uid, const char *passwd, const char *nonce) |
| 107 | /* hashes a password */ | 107 | /* hashes a password */ |
| 108 | { | 108 | { |
| 109 | xs *d_nonce = NULL; | 109 | xs *d_nonce = NULL; |
| @@ -120,7 +120,7 @@ d_char *hash_password(char *uid, char *passwd, char *nonce) | |||
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | 122 | ||
| 123 | int check_password(char *uid, char *passwd, char *hash) | 123 | int check_password(const char *uid, const char *passwd, const char *hash) |
| 124 | /* checks a password */ | 124 | /* checks a password */ |
| 125 | { | 125 | { |
| 126 | int ret = 0; | 126 | int ret = 0; |
| @@ -36,17 +36,17 @@ typedef struct _snac { | |||
| 36 | d_char *md5; /* actor url md5 */ | 36 | d_char *md5; /* actor url md5 */ |
| 37 | } snac; | 37 | } snac; |
| 38 | 38 | ||
| 39 | int user_open(snac *snac, char *uid); | 39 | int user_open(snac *snac, const char *uid); |
| 40 | void user_free(snac *snac); | 40 | void user_free(snac *snac); |
| 41 | d_char *user_list(void); | 41 | d_char *user_list(void); |
| 42 | 42 | ||
| 43 | void snac_debug(snac *snac, int level, d_char *str); | 43 | void snac_debug(snac *snac, int level, d_char *str); |
| 44 | #define snac_log(snac, str) snac_debug(snac, 0, str) | 44 | #define snac_log(snac, str) snac_debug(snac, 0, str) |
| 45 | 45 | ||
| 46 | int validate_uid(char *uid); | 46 | int validate_uid(const char *uid); |
| 47 | 47 | ||
| 48 | d_char *hash_password(char *uid, char *passwd, char *nonce); | 48 | d_char *hash_password(const char *uid, const char *passwd, const char *nonce); |
| 49 | int check_password(char *uid, char *passwd, char *hash); | 49 | int check_password(const char *uid, const char *passwd, const char *hash); |
| 50 | 50 | ||
| 51 | void srv_archive(char *direction, char *req, char *payload, int p_size, | 51 | void srv_archive(char *direction, char *req, char *payload, int p_size, |
| 52 | int status, char *headers, char *body, int b_size); | 52 | int status, char *headers, char *body, int b_size); |
| @@ -173,4 +173,5 @@ int html_post_handler(d_char *req, char *q_path, d_char *payload, int p_size, | |||
| 173 | char **body, int *b_size, char **ctype); | 173 | char **body, int *b_size, char **ctype); |
| 174 | 174 | ||
| 175 | int initdb(const char *_basedir); | 175 | int initdb(const char *_basedir); |
| 176 | int adduser(char *uid); | 176 | int adduser(const char *uid); |
| 177 | int resetpwd(snac *snac); | ||
| @@ -187,13 +187,27 @@ int initdb(const char *basedir) | |||
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | 189 | ||
| 190 | int adduser(char *uid) | 190 | void new_password(const char *uid, d_char **clear_pwd, d_char **hashed_pwd) |
| 191 | /* creates a random password */ | ||
| 192 | { | ||
| 193 | int rndbuf[3]; | ||
| 194 | |||
| 195 | srandom(time(NULL) ^ getpid()); | ||
| 196 | rndbuf[0] = random() & 0xffffffff; | ||
| 197 | rndbuf[1] = random() & 0xffffffff; | ||
| 198 | rndbuf[2] = random() & 0xffffffff; | ||
| 199 | |||
| 200 | *clear_pwd = xs_base64_enc((char *)rndbuf, sizeof(rndbuf)); | ||
| 201 | *hashed_pwd = hash_password(uid, *clear_pwd, NULL); | ||
| 202 | } | ||
| 203 | |||
| 204 | |||
| 205 | int adduser(const char *uid) | ||
| 191 | /* creates a new user */ | 206 | /* creates a new user */ |
| 192 | { | 207 | { |
| 193 | snac snac; | 208 | snac snac; |
| 194 | xs *config = xs_dict_new(); | 209 | xs *config = xs_dict_new(); |
| 195 | xs *date = xs_str_utctime(0, "%Y-%m-%dT%H:%M:%SZ"); | 210 | xs *date = xs_str_utctime(0, "%Y-%m-%dT%H:%M:%SZ"); |
| 196 | int rndbuf[3]; | ||
| 197 | xs *pwd = NULL; | 211 | xs *pwd = NULL; |
| 198 | xs *pwd_f = NULL; | 212 | xs *pwd_f = NULL; |
| 199 | xs *key = NULL; | 213 | xs *key = NULL; |
| @@ -214,13 +228,7 @@ int adduser(char *uid) | |||
| 214 | return 1; | 228 | return 1; |
| 215 | } | 229 | } |
| 216 | 230 | ||
| 217 | srandom(time(NULL) ^ getpid()); | 231 | new_password(uid, &pwd, &pwd_f); |
| 218 | rndbuf[0] = random() & 0xffffffff; | ||
| 219 | rndbuf[1] = random() & 0xffffffff; | ||
| 220 | rndbuf[2] = random() & 0xffffffff; | ||
| 221 | |||
| 222 | pwd = xs_base64_enc((char *)rndbuf, sizeof(rndbuf)); | ||
| 223 | pwd_f = hash_password(uid, pwd, NULL); | ||
| 224 | 232 | ||
| 225 | config = xs_dict_append(config, "uid", uid); | 233 | config = xs_dict_append(config, "uid", uid); |
| 226 | config = xs_dict_append(config, "name", uid); | 234 | config = xs_dict_append(config, "name", uid); |
| @@ -302,3 +310,32 @@ int adduser(char *uid) | |||
| 302 | 310 | ||
| 303 | return 0; | 311 | return 0; |
| 304 | } | 312 | } |
| 313 | |||
| 314 | |||
| 315 | int resetpwd(snac *snac) | ||
| 316 | /* creates a new password for the user */ | ||
| 317 | { | ||
| 318 | xs *clear_pwd = NULL; | ||
| 319 | xs *hashed_pwd = NULL; | ||
| 320 | xs *fn = xs_fmt("%s/user.json", snac->basedir); | ||
| 321 | FILE *f; | ||
| 322 | int ret = 0; | ||
| 323 | |||
| 324 | new_password(snac->uid, &clear_pwd, &hashed_pwd); | ||
| 325 | |||
| 326 | snac->config = xs_dict_set(snac->config, "passwd", hashed_pwd); | ||
| 327 | |||
| 328 | if ((f = fopen(fn, "w")) != NULL) { | ||
| 329 | xs *j = xs_json_dumps_pp(snac->config, 4); | ||
| 330 | fwrite(j, strlen(j), 1, f); | ||
| 331 | fclose(f); | ||
| 332 | |||
| 333 | printf("New password for user %s is %s\n", snac->uid, clear_pwd); | ||
| 334 | } | ||
| 335 | else { | ||
| 336 | printf("ERROR: cannot write to %s\n", fn); | ||
| 337 | ret = 1; | ||
| 338 | } | ||
| 339 | |||
| 340 | return ret; | ||
| 341 | } | ||