#include #include #include #include #include "compat.h" #include "buffer.h" #include "md5.h" /* ---------------------------------------------------------------------------------- * FORWARD DECLs */ static void usage(); static void process_file(ha_buffer_t* buf, int simple, int in); static void process_ha1(ha_buffer_t* buf, const char* user, const char* realm, const char* password); static char* check_value(ha_buffer_t* buf, char* value, const char* name); /* ---------------------------------------------------------------------------------- * USER INTERACTION */ int main(int argc, char* argv[]) { char* user = NULL; char* realm = NULL; char* password = NULL; int delimited = 0; int simple = 0; ha_buffer_t buf; int ch; while((ch = getopt(argc, argv, "dp:r:su:")) != -1) { switch(ch) { case 'd': delimited = 1; break; case 'p': password = optarg; break; case 'r': realm = optarg; break; case 's': simple = 1; break; case 'u': user = optarg; break; case '?': default: usage(); break; }; } argc -= optind; argv += optind; if(argc != 0) usage(); ha_bufinit(&buf); if(delimited) { process_file(&buf, simple, 0); } else { user = check_value(&buf, user, "username"); realm = check_value(&buf, realm, "realm"); password = check_value(&buf, password, "password"); process_ha1(&buf, user, realm, password); } return 0; } static void usage() { fprintf(stderr, "usage: mkha1 [-u user] [-r realm] [-p password]\n"); fprintf(stderr, " mkha1 -d [-s]\n"); exit(2); } static char* check_value(ha_buffer_t* buf, char* value, const char* name) { if(!value) { char* t = (char*)ha_bufmalloc(buf, 256); if(t == NULL) err(1, "out of memory"); printf("%s: ", name); fgets(t, 256, stdin); value = t; } if(value[0] == 0) errx("%s is empty"); if(strchr(value, ':') != NULL) errx("%s must be a not contain colons"); return value; } /* ---------------------------------------------------------------------------------- * FUNCTIONALITY */ static void process_ha1(ha_buffer_t* buf, const char* user, const char* realm, const char* password) { unsigned char hash[MD5_LEN]; md5_ctx_t md5; const char* t; ASSERT(buf && user && realm && password); md5_init(&md5); md5_update(&md5, user, strlen(user)); md5_update(&md5, ":", 1); md5_update(&md5, realm, strlen(realm)); md5_update(&md5, ":", 1); md5_update(&md5, password, strlen(password)); md5_final(hash, &md5); t = ha_bufenchex(buf, hash, MD5_LEN); printf("%s\n", t); } static void process_file(ha_buffer_t* buf, int simple, int in) { const char* user; const char* realm; const char* password; int more = 1; int r; ASSERT(buf); while(more) { r = ha_bufreadline(in, buf); if(r < 0) err(1, "error reading input"); if(r == 0) more = 0; user = ha_bufparseword(buf, ":"); realm = ha_bufparseword(buf, ":"); password = ha_bufparseline(buf, 0); if(ha_buferr(buf)) err(1, "out of memory"); if(!user || !user[0] || !realm || !realm[0] || !password || !password[0] || strchr(password, ':') != NULL) { warnx("invalid input line. Must be in the form \"user:realm:password\""); continue; } if(!simple) printf("%s:%s:", user, realm); process_ha1(buf, user, realm, password); ha_bufreset(buf); } }