"Fossies" - the Fresh Open Source Software archive

Member "httpauth-0.9.5/tools/mkha1.c" of archive httpauth-0.9.5.tar.gz:


/*
 * 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 <stef@memberwebs.com>
 *
 */

#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#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);
    }
}