1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-26 18:36:38 +02:00
Files
unrealircd/src/auth.c
T
2002-02-16 20:15:41 +00:00

329 lines
6.8 KiB
C

/*
* Unreal Internet Relay Chat Daemon, src/auth.c
* (C) 2001 Carsten V. Munk (stskeeps@tspre.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "channel.h"
#include "version.h"
#include <time.h>
#ifdef _WIN32
#include <sys/timeb.h>
#endif
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#endif
#include <fcntl.h>
#include "h.h"
anAuthStruct AuthTypes[] = {
{"plain", AUTHTYPE_PLAINTEXT},
{"plaintext", AUTHTYPE_PLAINTEXT},
#ifdef AUTHENABLE_UNIXCRYPT
{"crypt", AUTHTYPE_UNIXCRYPT},
{"unixcrypt", AUTHTYPE_UNIXCRYPT},
#endif
#ifdef AUTHENABLE_MD5
{"md5", AUTHTYPE_MD5},
#endif
#ifdef AUTHENABLE_SHA1
{"sha1", AUTHTYPE_SHA1},
#endif
#ifdef AUTHENABLE_SSL_PUBKEY
{"sslpubkey", AUTHTYPE_SSL_PUBKEY},
#endif
{NULL, 0}
};
int Auth_FindType(char *type)
{
anAuthStruct *p = AuthTypes;
while (p->data)
{
if (!strcmp(p->data, type))
return p->type;
p++;
}
return -1;
}
/*
* This is for converting something like:
* {
* password "data" { type; };
* }
*/
anAuthStruct *Auth_ConvertConf2AuthStruct(ConfigEntry *ce)
{
short type = AUTHTYPE_PLAINTEXT;
anAuthStruct *as = NULL;
/* If there is a {}, use it */
if (ce->ce_entries)
{
if (ce->ce_entries->ce_varname)
{
type = Auth_FindType(ce->ce_entries->ce_varname);
if (type == -1)
{
config_error("%s:%i: authentication module failure: %s is not an implemented/enabled authentication method",
ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
ce->ce_entries->ce_varname);
return NULL;
}
}
}
if (!ce->ce_vardata)
{
config_error("%s:%i: authentication module failure: missing parameter",
ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
ce->ce_entries->ce_varname);
return NULL;
}
as = (anAuthStruct *) MyMalloc(sizeof(anAuthStruct));
as->data = strdup(ce->ce_vardata);
as->type = type;
return as;
}
void Auth_DeleteAuthStruct(anAuthStruct *as)
{
if (!as)
return;
if (as->data)
MyFree(as->data);
MyFree(as);
}
/*
* cptr MUST be a local client
* as is what it will be compared with
* para will used in coordination with the auth type
*/
/*
* -1 if authentication failed
* 1 if authentication succeeded
* 2 if authentication succeeded, using parameter
* -2 if authentication is delayed, don't error
* No AuthStruct = everyone allowed
*/
int Auth_Check(aClient *cptr, anAuthStruct *as, char *para)
{
#ifdef AUTHENABLE_UNIXCRYPT
extern char *crypt();
#endif
#if defined(AUTHENABLE_MD5) || defined(AUTHENABLE_SHA1)
static char buf[512];
int i;
#endif
#ifdef AUTHENABLE_MD5
MD5_CTX md5_ctx;
#endif
#ifdef AUTHENABLE_SHA1
SHA_CTX sha1_ctx;
#endif
#ifdef AUTHENABLE_SSL_PUBKEY
EVP_PKEY *evp_pkey = NULL;
EVP_PKEY *evp_pkeyfile = NULL;
X509 *x509_client = NULL;
FILE *key_file = NULL;
#endif
if (!as)
return 1;
switch (as->type)
{
case AUTHTYPE_PLAINTEXT:
if (!para)
return -1;
/* plain text compare */
if (!strcmp(para, as->data))
return 2;
else
return -1;
break;
#ifdef AUTHENABLE_UNIXCRYPT
case AUTHTYPE_UNIXCRYPT:
if (!para)
return -1;
/* If our data is like 1 or none, we just let em through .. */
if (!(as->data[0] && as->data[1]))
return 1;
if (!strcmp(crypt(para, as->data), as->data))
return 2;
else
return -1;
break;
#endif
#ifdef AUTHENABLE_MD5
case AUTHTYPE_MD5:
if (!para)
return -1;
if ((i = b64_encode(MD5(para, strlen(para), NULL),
MD5_DIGEST_LENGTH, buf, sizeof(buf))))
{
if (!strcmp(buf, as->data))
return 2;
else
return -1;
}
else
return -1;
break;
#endif
#ifdef AUTHENABLE_SHA1
case AUTHTYPE_SHA1:
if (!para)
return -1;
if ((i = b64_encode(SHA1(para, strlen(para), NULL),
SHA_DIGEST_LENGTH, buf, sizeof(buf))))
{
if (!strcmp(buf, as->data))
return 2;
else
return -1;
}
else
return -1;
break;
#endif
#ifdef AUTHENABLE_SSL_PUBKEY
case AUTHTYPE_SSL_PUBKEY:
if (!para)
return -1;
if (!cptr->ssl)
return -1;
x509_client = SSL_get_peer_certificate((SSL *)cptr->ssl);
if (!x509_client)
return -1;
evp_pkey = X509_get_pubkey(x509_client);
if (!(key_file = fopen(para, "r")))
{
EVP_PKEY_free(evp_pkey);
X509_free(x509_client);
return -1;
}
evp_pkeyfile = PEM_read_PUBKEY(key_file, NULL,
NULL, NULL);
if (!evp_pkeyfile)
{
fclose(key_file);
EVP_PKEY_free(evp_pkey);
X509_free(x509_client);
return -1;
}
if (!(EVP_PKEY_cmp_parameters(evp_pkeyfile, evp_pkey)))
{
fclose(key_file);
EVP_PKEY_free(evp_pkey);
EVP_PKEY_free(evp_pkeyfile);
X509_free(x509_client);
return -1;
}
fclose(key_file);
EVP_PKEY_free(evp_pkey);
EVP_PKEY_free(evp_pkeyfile);
X509_free(x509_client);
return 2;
#endif
}
return -1;
}
char *Auth_Make(short type, char *para)
{
#ifdef AUTHENABLE_UNIXCRYPT
char salt[3];
extern char *crypt();
#endif
#if defined(AUTHENABLE_MD5) || defined(AUTHENABLE_SHA1)
static char buf[512];
int i;
#endif
#ifdef AUTHENABLE_MD5
MD5_CTX md5_ctx;
#endif
#ifdef AUTHENABLE_SHA1
SHA_CTX sha1_ctx;
#endif
switch (type)
{
case AUTHTYPE_PLAINTEXT:
return (para);
break;
#ifdef AUTHENABLE_UNIXCRYPT
case AUTHTYPE_UNIXCRYPT:
if (!para)
return NULL;
/* If our data is like 1 or none, we just let em through .. */
if (!(para[0] && para[1]))
return NULL;
sprintf(salt, "%02X", (rand() >> 24) & 0xFF);
return(crypt(para, salt));
break;
#endif
#ifdef AUTHENABLE_MD5
case AUTHTYPE_MD5:
if (!para)
return NULL;
if ((i = b64_encode(MD5(para, strlen(para), NULL),
MD5_DIGEST_LENGTH, buf, sizeof(buf))))
{
return (buf);
}
else
return NULL;
break;
#endif
#ifdef AUTHENABLE_SHA1
case AUTHTYPE_SHA1:
if (!para)
return NULL;
if ((i = b64_encode(SHA1(para, strlen(para), NULL),
SHA_DIGEST_LENGTH, buf, sizeof(buf))))
{
return (buf);
}
else
return NULL;
break;
#endif
default:
return (NULL);
}
}