1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
/*
* DDNS v3 Client
*
* Author: Alan Yates <alany@ay.com.au>
* Version: $Id: auth.c,v 1.1.1.1 2002/07/19 11:47:20 alany Exp $
*/
#define _XOPEN_SOURCE
#ifdef WIN32
#include <windows.h>
#include <process.h>
#else
#include <unistd.h>
#endif
#include <string.h>
#include "ctx.h"
#include "auth.h"
#include "crypto.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static char *ddns3_auth_salts =
"abcdefghijklmnopqrstuzwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890./";
static int
auth_plaintext(struct ddns3_ctx *c, char *user, char *passwd) {
if(!strstr(c->hello, "plaintext")) return -1;
sprintf(c->buf, "LOGIN %s %s", user, passwd);
return 0;
}
#ifndef WIN32
static int
auth_crypt(struct ddns3_ctx *c, char *user, char *passwd) {
char salt[2];
char *hash;
if(!strstr(c->hello, "crypt")) return -1;
srand(getpid() * time(0));
salt[0] = ddns3_auth_salts[rand() % strlen(ddns3_auth_salts)];
salt[1] = ddns3_auth_salts[rand() % strlen(ddns3_auth_salts)];
hash = ddns3_crypto_crypt(passwd, salt);
sprintf(c->buf, "LOGIN %s %s", user, hash);
free(hash);
return 0;
}
#endif
static int
auth_md5(struct ddns3_ctx *c, char *user, char *passwd) {
char *hash;
if(!strstr(c->hello, "md5")) return -1;
hash = ddns3_crypto_md5hash(passwd, strlen(passwd));
sprintf(c->buf, "LOGIN %s %s", user, hash);
free(hash);
return 0;
}
static int
auth_ddns(struct ddns3_ctx *c, char *user, char *passwd) {
char *hash, *p;
char buf[4096];
if(!strstr(c->hello, "ddns")) return -1;
strcpy(buf, passwd);
strcat(buf, ":");
p = strstr(c->hello, "ddns{");
strncat(buf, p+5, 32);
hash = ddns3_crypto_md5hash(buf, strlen(buf));
sprintf(c->buf, "LOGIN %s %s", user, hash);
free(hash);
return 0;
}
/* FIXME: there is no server support for strong auth yet */
static int
auth_strong(struct ddns3_ctx *c, char *user, char *passwd) {
char *phash, *uhash, *challenge, *p;
char buf[4096];
int i;
if(!strstr(c->hello, "ddns")) return -1;
/* password hash */
strcpy(buf, passwd);
strcat(buf, ":");
p = strstr(c->hello, "ddns{");
strncat(buf, p+5, 32);
phash = ddns3_crypto_md5hash(buf, strlen(buf));
/* random challenge */
srand(getpid() * time(0));
for(i = 0; i < 100; i++) buf[i] = rand();
challenge = ddns3_crypto_md5hash(buf, 100);
/* username hash */
strcpy(buf, user);
strcat(buf, ":");
strncat(buf, challenge, 32);
uhash = ddns3_crypto_md5hash(buf, strlen(buf));
sprintf(c->buf, "LOGIN %s %s %s", uhash, phash, challenge);
free(uhash);
free(phash);
free(challenge);
return 0;
}
static struct ddns3_auth known_auths[] = {
{"plaintext", auth_plaintext},
#ifndef WIN32
{"crypt", auth_crypt},
#endif
{"md5", auth_md5},
{"ddns", auth_ddns},
{"strong", auth_strong},
{0, 0}
};
int
ddns3_auth_makechallenge(struct ddns3_ctx *c, char *auth, char *user, char *passwd) {
int i;
int ret = -2;
for(i = 0; known_auths[i].name; i++)
if(!strcmp(known_auths[i].name, auth)) {
ret = known_auths[i].makechallenge(c, user, passwd);
break;
}
if(ret < -1)
strcpy(c->buf, "client_error: authentication type unknown to client\n");
else if(ret < 0)
strcpy(c->buf, "client_error: authentication type not supported by server\n");
return ret;
}
|