/* * Copyright (c) 2004, Stefan Walter * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or * other materials provided with the distribution. * * The names of contributors to this software may not be * used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * * CONTRIBUTORS * Stef Walter * */ #include #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 batch = 0; int simple = 0; ha_buffer_t buf; int ch; while((ch = getopt(argc, argv, "bp:r:su:")) != -1) { switch(ch) { case 'b': batch = 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(batch) { 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 -b [-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; t = value + strlen(value); /* Remove any new lines from end */ while(t > value && (*(t - 1) == '\n' || *(t - 1) == '\r')) *(--t) = 0; } if(value[0] == 0) errx(1, "%s is empty", name); if(strchr(value, ':') != NULL) errx(1, "%s must be a not contain colons", name); 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); } }