/* * Sauerbraten coopedit helper bot * * Copyright (C) 2007 Michael Buesch * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include "main.h" #include "auth.h" #include #include #include #include static char random_char_from_array(const char *array, size_t len) { return array[random_int() % len]; } /* sizeof(buf) >= len + 1 */ static void gen_pronounceable_string(char *buf, size_t len) { static const char *consonants = "bcdfghjklmnpqrstvwx"; /* no y,z */ static const char *vowels = "aeiou"; const size_t consonants_len = strlen(consonants); const size_t vowels_len = strlen(vowels); enum { TYPE_RANDOM, TYPE_CONSONANT, TYPE_VOWEL, } next_type; int nr_consonants = 0; int nr_vowels = 0; int rnd; size_t i; char c; for (i = 0; i < len; i++) { if (i == 1 && nr_consonants == 1) { /* Do not start with two consonants */ next_type = TYPE_VOWEL; nr_consonants = 0; } else if (nr_vowels == 1) { next_type = TYPE_CONSONANT; nr_vowels = 0; } else if (nr_consonants == 2) { next_type = TYPE_VOWEL; nr_consonants = 0; } else next_type = TYPE_RANDOM; if (next_type == TYPE_RANDOM) { rnd = random_int() % 2; if (rnd == 0) next_type = TYPE_CONSONANT; else next_type = TYPE_VOWEL; } switch (next_type) { case TYPE_CONSONANT: c = random_char_from_array(consonants, consonants_len); buf[i] = c; nr_consonants++; break; case TYPE_VOWEL: c = random_char_from_array(vowels, vowels_len); buf[i] = c; nr_vowels++; break; case TYPE_RANDOM: /* Can't happen */ fprintf(stderr, "TYPE_RANDOM\n"); exit(1); } } buf[i] = '\0'; } void gen_authmap(struct sbot_authmap *map) { struct sbot_authkey *key; int i; for (i = 0; i < NR_AUTHKEYS; i++) { key = &(map->keys[i]); gen_pronounceable_string(key->key, AUTHKEY_LEN); } map->mapid = (random_int() & 0xFFFF); } int do_export_authmap(const struct sbot_authmap *map, FILE *fd) { unsigned int i; time_t t; struct tm *loc; t = time(NULL); loc = localtime(&t); fprintf(fd, "# Sauerbot authentication map.\n"); fprintf(fd, "# This is private information.\n"); fprintf(fd, "#\n"); fprintf(fd, "# %s", asctime(loc)); fprintf(fd, "#\n"); fprintf(fd, "\n"); fprintf(fd, "MAPID: %04X\n", map->mapid); fprintf(fd, "\n"); for (i = 0; i < NR_AUTHKEYS; i++) { if ((i % 5 == 0) && (i != 0)) fprintf(fd, "\n"); fprintf(fd, "%02u: %s ", i, map->keys[i].key); } fprintf(fd, "\n"); return 0; } int export_authmap(const struct sbot_authmap *map, const char *file) { FILE *fd; int err; printf("Exporting authentication map...\n"); fd = fopen(file, "w+"); if (!fd) { fprintf(stderr, "Could not open authmap export file %s: %s\n", file, strerror(errno)); return -1; } err = do_export_authmap(map, fd); if (err) { fprintf(stderr, "Failed to write authmap export file \"%s\"\n", file);\ fclose(fd); return -1; } fclose(fd); return 0; } int do_import_authmap(struct sbot_authmap *map, FILE *fd) { ssize_t len; size_t blen = 0; char *buf = NULL; unsigned int tmp, i; unsigned int a, b, c, d, e; char b1[21]; char b2[21]; char b3[21]; char b4[21]; char b5[21]; memset(map, 0, sizeof(*map)); while ((len = getline(&buf, &blen, fd)) > 0) { if (buf[0] == '#') continue; if (sscanf(buf, "MAPID: %04X", &tmp) == 1) { map->mapid = tmp; map->mapid_ok = 1; continue; } if (sscanf(buf, "%02u: %20s %02u: %20s %02u: %20s %02u: %20s %02u: %20s", &a, b1, &b, b2, &c, b3, &d, b4, &e, b5) == 10) { if ((b != a + 1) || (c != a + 2) || (d != a + 3) || (e != a + 4)) continue; if (e >= NR_AUTHKEYS) continue; strncpy(map->keys[a].key, b1, AUTHKEY_LEN); map->keys[a].ok = 1; strncpy(map->keys[b].key, b2, AUTHKEY_LEN); map->keys[b].ok = 1; strncpy(map->keys[c].key, b3, AUTHKEY_LEN); map->keys[c].ok = 1; strncpy(map->keys[d].key, b4, AUTHKEY_LEN); map->keys[d].ok = 1; strncpy(map->keys[e].key, b5, AUTHKEY_LEN); map->keys[e].ok = 1; } } if (!map->mapid_ok) fprintf(stderr, "Authmap import: Missing MAPID number\n"); for (i = 0; i < NR_AUTHKEYS; i++) { if (!map->keys[i].ok) { fprintf(stderr, "Authmap import: Corrupt authmap data\n"); memset(map, 0, sizeof(*map)); return -1; } } return 0; } int import_authmap(struct sbot_authmap *map, const char *file) { FILE *fd; int err; printf("Importing authentication map...\n"); fd = fopen(file, "r"); if (!fd) { fprintf(stderr, "Could not open authentication map %s: %s\n", file, strerror(errno)); return -1; } err = do_import_authmap(map, fd); if (err) { fprintf(stderr, "Failed to parse authmap file \"%s\"\n", file); fclose(fd); return -1; } fclose(fd); return 0; }