diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2000-12-20 01:41:54 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2000-12-20 01:41:54 +0000 |
commit | cffcf376225c41635be9c952a0a26c0c0f12d4e7 (patch) | |
tree | d56292c95b8b6140045f29baf9e41f0c6d177b51 /libexec/login_token | |
parent | 005d89db1e301780453d7ba2b1ba4f9c0c7ae81a (diff) |
Provides ActivCard, CRYPTOCard and SNK-004 authentication from BSDi
Will be used when BSD authentication is enabled
Diffstat (limited to 'libexec/login_token')
-rw-r--r-- | libexec/login_token/Makefile | 27 | ||||
-rw-r--r-- | libexec/login_token/init.c | 126 | ||||
-rw-r--r-- | libexec/login_token/login_token.8 | 102 | ||||
-rw-r--r-- | libexec/login_token/login_token.c | 174 | ||||
-rw-r--r-- | libexec/login_token/token.c | 411 | ||||
-rw-r--r-- | libexec/login_token/token.h | 84 | ||||
-rw-r--r-- | libexec/login_token/tokendb.c | 343 | ||||
-rw-r--r-- | libexec/login_token/tokendb.h | 80 |
8 files changed, 1347 insertions, 0 deletions
diff --git a/libexec/login_token/Makefile b/libexec/login_token/Makefile new file mode 100644 index 00000000000..840383dddd7 --- /dev/null +++ b/libexec/login_token/Makefile @@ -0,0 +1,27 @@ +# $OpenBSD: Makefile,v 1.1 2000/12/20 01:41:52 millert Exp $ + +PROG= login_token +SRCS= login_token.c init.c token.c tokendb.c +MAN= login_token.8 +DPADD= ${LIBDES} +LDADD= -ldes + +TOKENS= activ crypto snk + +MLINKS= login_token.8 login_activ.8 +MLINKS+=login_token.8 login_crypto.8 +MLINKS+=login_token.8 login_snk.8 + +afterinstall: + for i in ${TOKENS} ; do \ + cd ${DESTDIR}/${BINDIR} && \ + rm -f login_$$i && \ + ln ${PROG} login_$$i ; \ + done + +BINOWN= root +BINGRP= auth +BINMODE=4555 +BINDIR= /usr/libexec/auth + +.include <bsd.prog.mk> diff --git a/libexec/login_token/init.c b/libexec/login_token/init.c new file mode 100644 index 00000000000..eaeadefda34 --- /dev/null +++ b/libexec/login_token/init.c @@ -0,0 +1,126 @@ +/* $OpenBSD: init.c,v 1.1 2000/12/20 01:41:53 millert Exp $ */ + +/*- + * Copyright (c) 1996 Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Berkeley Software Design, + * Inc. + * 4. The name of Berkeley Software Design, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``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 BERKELEY SOFTWARE DESIGN, INC. 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. + * + * BSDI $From: init.c,v 1.2 1996/09/05 23:17:06 prb Exp $ + */ + +#include <sys/types.h> +#include <stdio.h> +#include <string.h> + +#include "token.h" +#include "tokendb.h" + +static struct token_types types[] = { + { "activ", "ActivCard", "/etc/activ.db", "012345", + TOKEN_HEXINIT, + TOKEN_DECMODE | TOKEN_HEXMODE, /* avail */ + TOKEN_HEXMODE }, /* default */ + { "crypto", "CRYPTOCard", "/etc/crypto.db", "012345", + TOKEN_HEXINIT | TOKEN_PHONE, + TOKEN_DECMODE | TOKEN_HEXMODE | TOKEN_PHONEMODE | TOKEN_RIM, + TOKEN_HEXMODE }, /* default */ + { "snk", "SNK 004", "/etc/snk.db", "222333", + 0, + TOKEN_DECMODE | TOKEN_HEXMODE, /* avail */ + TOKEN_DECMODE }, /* default */ + { "token", "X9.9 Token", "/etc/x99token.db", "012345", + TOKEN_HEXINIT, + TOKEN_DECMODE | TOKEN_HEXMODE | TOKEN_RIM, /* avail */ + TOKEN_HEXMODE }, /* default */ +}; + +static struct { + char *name; + u_int value; +} modes[] = { + { "hexadecimal", TOKEN_HEXMODE }, + { "hex", TOKEN_HEXMODE }, + { "decimal", TOKEN_DECMODE }, + { "dec", TOKEN_DECMODE }, + { "phonebook", TOKEN_PHONEMODE }, + { "phone", TOKEN_PHONEMODE }, + { "reduced-input", TOKEN_RIM }, + { "rim", TOKEN_RIM } +}; + +int +token_init(char *path) +{ + char *p; + int i; + + if ((p = strrchr(path, '/')) && p[1] != '\0') + path = p + 1; + + for (i = 0; i < sizeof(types)/sizeof(types[0]); ++i) + if (strstr(path, types[i].name) != NULL) { + tt = &types[i]; + return (0); + } + if ((p = strstr(path, "token")) != NULL) { + fprintf(stderr, "Please invoke as one of:"); + for (i = 0; i < sizeof(types)/sizeof(types[0]); ++i) + fprintf(stderr, " %.*s%s%s", + p - path, path, types[i].name, p + 5); + fprintf(stderr, "\n"); + exit(1); + + } + return (-1); +} + +u_int +token_mode(char *mode) +{ + int i; + + for (i = 0; i < sizeof(modes)/sizeof(modes[0]); ++i) + if (strstr(mode, modes[i].name) != NULL) + return (tt->modes & modes[i].value); + return (0); + return (0); +} + +char * +token_getmode(u_int mode) +{ + int i; + static char buf[32]; + + for (i = 0; i < sizeof(modes)/sizeof(modes[0]); ++i) + if (mode == modes[i].value) + return(modes[i].name); + snprintf(buf, sizeof(buf), "0x%x", mode); + return(buf); +} diff --git a/libexec/login_token/login_token.8 b/libexec/login_token/login_token.8 new file mode 100644 index 00000000000..404137656cb --- /dev/null +++ b/libexec/login_token/login_token.8 @@ -0,0 +1,102 @@ +.\" $OpenBSD: login_token.8,v 1.1 2000/12/20 01:41:53 millert Exp $ +.\" +.\" Copyright (c) 1995 Berkeley Software Design, Inc. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. 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. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Berkeley Software Design, +.\" Inc. +.\" 4. The name of Berkeley Software Design, Inc. may not be used to endorse +.\" or promote products derived from this software without specific prior +.\" written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``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 BERKELEY SOFTWARE DESIGN, INC. 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. +.\" +.Dd September 26, 1995 +.Dt LOGIN_TOKEN 8 +.Os +.Sh NAME +.Nm login_activ , login_crypto , login_snk +.Nd provide ActivCard, CRYPTOCard and SNK-004 authentication +.Sh SYNOPSIS +.Nm login_token +.Op Fl s Ar service +.Op Fl v Ar name=value +.Ar user +.Op Ar class +.Sh DESCRIPTION +.Pp +The +.Nm login_token +program implements a X9.9 token card challenge response authentication +mechanism (see +.Xr login.conf 5 ) . +It must be invoked by one of the names: +.Nm login_activ , login_crypto , +or +.Nm login_snk . +.Pp +Available options are: +.Bl -tag -width indent +.It Fl s +Specify the service. Currently only +.Li challenge , +.Li login , +and +.Li response +are supported. +.It Fl v +This option and its value are ignored. +.El +.Pp +.Nm login_token +will look up +.Ar user +in the the appropriate database file, depending on what name it was called as: +.Pa /etc/activ.db , +.Pa /etc/crypto.db , +or +.Pa /etc/snk.db . +It will then will issue a challenge, and if the user +is able to correctly respond (by using the appropriate token) +the user will be authenticated. +The +.Ar class +argument is unused. +.Sh DIAGNOSTICS +Diagnostic messages are logged via syslog(3) with the LOG_AUTH facility. +.Sh FILES +.Bl -tag -width xetcxcrypto.db +.It Pa /etc/activ.db +data base of information for the ActivCard tokens. +.It Pa /etc/crypto.db +data base of information for the CRYPTOCard tokens. +.It Pa /etc/snk.db +data base of information for the SNK-004 tokens. +.El +.Sh SEE ALSO +.Xr syslog 3 , +.Xr login.conf 5 , +.Xr tokenadm 8 , +.Xr tokenctl 8 , +.Xr tokeninit 8 +.Sh AUTHOR +Jack Flory <jpf@mig.com> diff --git a/libexec/login_token/login_token.c b/libexec/login_token/login_token.c new file mode 100644 index 00000000000..1e6461460d4 --- /dev/null +++ b/libexec/login_token/login_token.c @@ -0,0 +1,174 @@ +/* $OpenBSD: login_token.c,v 1.1 2000/12/20 01:41:53 millert Exp $ */ + +/*- + * Copyright (c) 1995, 1996 Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Berkeley Software Design, + * Inc. + * 4. The name of Berkeley Software Design, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``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 BERKELEY SOFTWARE DESIGN, INC. 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. + * + * BSDI $From: login_token.c,v 1.2 1996/09/04 05:33:05 prb Exp $ + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> + +#include <err.h> +#include <readpassphrase.h> +#include <stdio.h> +#include <syslog.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <login_cap.h> +#include <bsd_auth.h> + +#include "token.h" + +int +main(argc, argv) + int argc; + char **argv; +{ + FILE *back = NULL; + char *class = 0; + char *username = 0; + char *instance; + char challenge[1024]; + char response[1024]; + char *pp; + int c; + int mode = 0; + struct rlimit cds; + + (void)signal(SIGQUIT, SIG_IGN); + (void)signal(SIGINT, SIG_IGN); + (void)setpriority(PRIO_PROCESS, 0, 0); + + openlog(NULL, LOG_ODELAY, LOG_AUTH); + + cds.rlim_cur = 0; + cds.rlim_max = 0; + if (setrlimit(RLIMIT_CORE, &cds) < 0) + syslog(LOG_ERR, "couldn't set core dump size to 0: %m"); + + if (token_init(argv[0]) < 0) { + syslog(LOG_ERR, "unknown token type"); + errx(1, "unknown token type"); + } + + while ((c = getopt(argc, argv, "ds:v:")) != EOF) + switch(c) { + case 'd': /* to remain undocumented */ + back = stdout; + break; + case 'v': + break; + case 's': /* service */ + if (strcmp(optarg, "login") == 0) + mode = 0; + else if (strcmp(optarg, "challenge") == 0) + mode = 1; + else if (strcmp(optarg, "response") == 0) + mode = 2; + else { + syslog(LOG_ERR, "%s: invalid service", optarg); + exit(1); + } + break; + default: + syslog(LOG_ERR, "usage error"); + exit(1); + } + + switch(argc - optind) { + case 2: + class = argv[optind + 1]; + case 1: + username = argv[optind]; + break; + default: + syslog(LOG_ERR, "usage error"); + exit(1); + } + + + if (back == NULL && (back = fdopen(3, "r+")) == NULL) { + syslog(LOG_ERR, "reopening back channel"); + exit(1); + } + if (mode == 2) { + mode = 0; + c = -1; + while (++c < sizeof(challenge) && + read(3, &challenge[c], 1) == 1) { + if (challenge[c] == '\0' && ++mode == 2) + break; + if (challenge[c] == '\0' && mode == 1) + pp = challenge + c + 1; + } + if (mode < 2) { + syslog(LOG_ERR, "protocol error on back channel"); + exit(1); + } + } else { + tokenchallenge(username, challenge, sizeof(challenge), + tt->proper); + if (mode == 1) { + fprintf(back, BI_VALUE " challenge %s\n", + auth_mkvalue(challenge)); + fprintf(back, BI_CHALLENGE "\n"); + exit(0); + } + + pp = readpassphrase(challenge, response, sizeof(response), 0); + if (!pp || *pp == '\0') { + char buf[64]; + snprintf(buf, sizeof(buf), "%s Response [echo on]: ", + tt->proper); + pp = readpassphrase(buf, response, sizeof(response), + RPP_ECHO_ON); + } + } + + if (tokenverify(username, challenge, pp) == 0) { + fprintf(back, BI_AUTH "\n"); + + if ((instance = strchr(username, '.'))) { + *instance++ = 0; + if (strcmp(instance, "root") == 0) + fprintf(back, BI_ROOTOKAY "\n"); + } + fprintf(back, BI_SECURE "\n"); + exit(0); + } + + fprintf(back, BI_REJECT "\n"); + exit(1); +} diff --git a/libexec/login_token/token.c b/libexec/login_token/token.c new file mode 100644 index 00000000000..5ac24a926e7 --- /dev/null +++ b/libexec/login_token/token.c @@ -0,0 +1,411 @@ +/* $OpenBSD: token.c,v 1.1 2000/12/20 01:41:53 millert Exp $ */ + +/*- + * Copyright (c) 1995 Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Berkeley Software Design, + * Inc. + * 4. The name of Berkeley Software Design, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``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 BERKELEY SOFTWARE DESIGN, INC. 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. + * + * BSDI $From: token.c,v 1.2 1996/08/28 22:07:55 prb Exp $ + */ + +/* + * DES functions for one-way encrypting Authentication Tokens. + * All knowledge of DES is confined to this file. + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> + +#include <ctype.h> +#include <stdio.h> +#include <syslog.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <des.h> + +#include "token.h" +#include "tokendb.h" + +/* + * Define a union of various types of arguments to DES functions. + * All native DES types are modulo 8 bytes in length. Cipher text + * needs a trailing null byte. + */ + +typedef union { + des_cblock cb; + char ct[9]; + unsigned long ul[2]; +} TOKEN_CBlock; + +/* + * Static definition of random number challenge for token. + * Challenge length is 8 bytes, left-justified with trailing null byte. + */ + +static TOKEN_CBlock tokennumber; + +/* + * Static function prototypes + */ + +static long tokenrandomnumber(void); +static void tokenseed(des_cblock); +static void lcase(char *); +static void h2d(char *); +static void h2cb(char *, TOKEN_CBlock *); +static void cb2h(TOKEN_CBlock, char *); + +/* + * Generate random DES cipherblock seed. Feedback key into + * new_random_key to strengthen. + */ + +static void +tokenseed(des_cblock cb) +{ + static int first_time = 1; + + if (first_time) { + first_time = 0; + des_random_key(cb); + des_init_random_number_generator(cb); + } + des_new_random_key(cb); +} + +/* + * Generate a random key of eight decimal digits. Actually, + * with the CRYPTOCard, this could be up to 64 digits. + * This string must be zero filled + * and padded to a 64-bit boundary with a trailing null byte. + * It could also be hex, but decimal is easier for the user + * to enter into the token. + */ + +static long +tokenrandomnumber(void) +{ + TOKEN_CBlock seed; + + tokenseed(seed.cb); + return (((seed.ul[0] ^ seed.ul[1]) % 99999999)); +} + +/* + * Send a random challenge string to the token. The challenge + * is always base 10 as there are no alpha keys on the keyboard. + */ + +void +tokenchallenge(char *user, char *challenge, int size, char *card_type) +{ + TOKENDB_Rec tr; + TOKEN_CBlock cb; + des_key_schedule ks; + int r, c; + + r = 1; /* no reduced input mode by default! */ + + if ((tt->modes & TOKEN_RIM) && + tokendb_getrec(user, &tr) == 0 && + (tr.mode & TOKEN_RIM)) { + c = 0; + while ((r = tokendb_lockrec(user, &tr, TOKEN_LOCKED)) == 1) { + if (c++ >= 60) + break; + sleep(1); + } + tr.flags &= ~TOKEN_LOCKED; + if (r == 0 && tr.rim[0]) { + h2cb(tr.secret, &cb); + des_fixup_key_parity(&cb.cb); + des_key_sched(&cb.cb, ks); + des_ecb_encrypt(&tr.rim, &cb.cb, ks, DES_ENCRYPT); + memcpy(tr.rim, cb.cb, 8); + for (r = 0; r < 8; ++r) { + if ((tr.rim[r] &= 0xf) > 9) + tr.rim[r] -= 10; + tr.rim[r] |= 0x30; + } + r = 0; /* reset it back */ + memcpy(tokennumber.ct, tr.rim, 8); + tokennumber.ct[8] = 0; + tokendb_putrec(user, &tr); + } + } + if (r != 0 || tr.rim[0] == '\0') { + memset(tokennumber.ct, 0, sizeof(tokennumber)); + snprintf(tokennumber.ct, sizeof(tokennumber.ct), "%08.8lu", + tokenrandomnumber()); + if (r == 0) { + memcpy(tr.rim, tokennumber.ct, 8); + tokendb_putrec(user, &tr); + } + } + + snprintf(challenge, size, "%s Challenge \"%s\"\r\n%s Response: ", + card_type, tokennumber.ct, card_type); +} + +/* + * Verify response from user against token's predicted cipher + * of the random number challenge. + */ + +int +tokenverify(char *username, char *challenge, char *response) +{ + char *state; + TOKENDB_Rec tokenrec; + TOKEN_CBlock tmp; + TOKEN_CBlock cmp_text; + TOKEN_CBlock user_seed; + TOKEN_CBlock cipher_text; + des_key_schedule key_schedule; + + + memset(cmp_text.ct, 0, sizeof(cmp_text)); + memset(user_seed.ct, 0, sizeof(user_seed)); + memset(cipher_text.ct, 0, sizeof(cipher_text)); + memset(tokennumber.ct, 0, sizeof(tokennumber)); + + state = strtok(challenge, "\""); + state = strtok(NULL, "\""); + tmp.ul[0] = strtoul(state, NULL, 10); + snprintf(tokennumber.ct, sizeof(tokennumber.ct), "%08.8lu",tmp.ul[0]); + + /* + * Retrieve the db record for the user. Nuke it as soon as + * we have translated out the user's shared secret just in + * case we (somehow) get core dumped... + */ + + if (tokendb_getrec(username, &tokenrec)) + return (-1); + + h2cb(tokenrec.secret, &user_seed); + memset((char*)&tokenrec.secret, 0, sizeof(tokenrec.secret)); + + if (!(tokenrec.flags & TOKEN_ENABLED)) + return (-1); + + /* + * Compute the anticipated response in hex. Nuke the user's + * shared secret asap. + */ + + des_fixup_key_parity(&user_seed.cb); + des_key_sched(&user_seed.cb, key_schedule); + memset(user_seed.ct, 0, sizeof(user_seed.ct)); + des_ecb_encrypt(&tokennumber.cb, &cipher_text.cb, key_schedule, + DES_ENCRYPT); + + /* + * The token thinks it's descended from VAXen. Deal with i386 + * endian-ness of binary cipher prior to generating ascii from first + * 32 bits. + */ + + HTONL(cipher_text.ul[0]); + snprintf(cmp_text.ct, sizeof(cmp_text.ct), "%08.8lx", cipher_text.ul[0]); + + if (tokenrec.mode & TOKEN_PHONEMODE) { + /* + * If we are a CRYPTOCard, we need to see if we are in + * "telephone number mode". If so, transmogrify the fourth + * digit of the cipher. Lower case response just in case + * it's * hex. Compare hex cipher with anticipated response + * from token. + */ + + lcase(response); + + if (response[3] == '-') + cmp_text.ct[3] = '-'; + } + + if ((tokenrec.mode & TOKEN_HEXMODE) && !strcmp(response, cmp_text.ct)) + return (0); + + /* + * No match against the computed hex cipher. The token could be + * in decimal mode. Pervert the string to magic decimal equivalent. + */ + + h2d(cmp_text.ct); + + if ((tokenrec.mode & TOKEN_DECMODE) && !strcmp(response, cmp_text.ct)) + return (0); + + return (-1); +} + +/* + * Initialize a new user record in the token database. + */ + +int +tokenuserinit(int flags, char *username, unsigned char *usecret, unsigned mode) +{ + TOKENDB_Rec tokenrec; + TOKEN_CBlock secret; + TOKEN_CBlock nulls; + TOKEN_CBlock checksum; + TOKEN_CBlock checktxt; + des_key_schedule key_schedule; + + /* + * If no user secret passed in, create one + */ + + if ( (flags & TOKEN_GENSECRET) ) + tokenseed(secret.cb); + else { + memset(&secret, 0, sizeof(secret)); + memcpy(&secret, usecret, sizeof(des_cblock)); + des_fixup_key_parity(&secret.cb); + } + + /* + * Check if the db record already exists. If no + * force-init flag and it exists, go away. Else, + * create the user's db record and put to the db. + */ + + + if (!(flags & TOKEN_FORCEINIT) && + tokendb_getrec(username, &tokenrec) == 0) + return (1); + + memset(&tokenrec, 0, sizeof(tokenrec)); + strncpy(tokenrec.uname, username, sizeof(tokenrec.uname)); + cb2h(secret, tokenrec.secret); + tokenrec.mode = 0; + tokenrec.flags = TOKEN_ENABLED | TOKEN_USEMODES; + tokenrec.mode = mode; + memset(tokenrec.reserved_char1, '0', sizeof(tokenrec.reserved_char1)); + memset(tokenrec.reserved_char2, '0', sizeof(tokenrec.reserved_char2)); + + if (tokendb_putrec(username, &tokenrec)) + return (-1); + + /* + * Check if the shared secret was generated here. If so, we + * need to inform the user about it in order that it can be + * programmed into the token. See tokenverify() (above) for + * discussion of cipher generation. + */ + + if (!(flags & TOKEN_GENSECRET)) + return (0); + + printf("Shared secret for %s\'s token: " + "%03o %03o %03o %03o %03o %03o %03o %03o\n", + username, secret.cb[0], secret.cb[1], secret.cb[2], secret.cb[3], + secret.cb[4], secret.cb[5], secret.cb[6], secret.cb[7]); + + + des_key_sched(&secret.cb, key_schedule); + memset(&nulls, 0, sizeof(nulls)); + des_ecb_encrypt(&nulls.cb, &checksum.cb, key_schedule, DES_ENCRYPT); + HTONL(checksum.ul[0]); + snprintf(checktxt.ct, sizeof(checktxt.ct), "%08.8lx", checksum.ul[0]); + printf("Hex Checksum: \"%s\"", checktxt.ct); + + h2d(checktxt.ct); + printf("\tDecimal Checksum: \"%s\"\n", checktxt.ct); + + return (0); +} + +/* + * Magically transform a hex character string into a decimal character + * string as defined by the token card vendor. The string should have + * been lowercased by now. + */ + +static void +h2d(char *cp) +{ + int i; + + for (i=0; i<sizeof(des_cblock); i++, cp++) { + if (*cp >= 'a' && *cp <= 'f') + *cp = tt->map[*cp - 'a']; + } +} + +/* + * Translate an hex 16 byte ascii representation of an unsigned + * integer to a des_cblock. + */ + +static void +h2cb(char *hp, TOKEN_CBlock *cb) +{ + char scratch[9]; + + strlcpy(scratch, hp, sizeof(scratch)); + cb->ul[0] = strtoul(scratch, NULL, 16); + + strlcpy(scratch, hp + 8, sizeof(scratch)); + cb->ul[1] = strtoul(scratch, NULL, 16); +} + +/* + * Translate a des_cblock to an 16 byte ascii hex representation. + */ + +static void +cb2h(TOKEN_CBlock cb, char* hp) +{ + char scratch[17]; + + snprintf(scratch, 9, "%08.8lx", cb.ul[0]); + snprintf(scratch+8, 9, "%08.8lx", cb.ul[1]); + memcpy(hp, scratch, 16); +} + +/* + * Lowercase possible hex response + */ + +static void +lcase(char *cp) +{ + while (*cp) { + if (isupper(*cp)) + *cp = tolower(*cp); + cp++; + } +} diff --git a/libexec/login_token/token.h b/libexec/login_token/token.h new file mode 100644 index 00000000000..e1d5baf54b6 --- /dev/null +++ b/libexec/login_token/token.h @@ -0,0 +1,84 @@ +/* $OpenBSD: token.h,v 1.1 2000/12/20 01:41:53 millert Exp $ */ + +/*- + * Copyright (c) 1995 Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Berkeley Software Design, + * Inc. + * 4. The name of Berkeley Software Design, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``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 BERKELEY SOFTWARE DESIGN, INC. 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. + * + * BSDI $From: token.h,v 1.1 1996/08/26 20:13:10 prb Exp $ + */ + +/* + * Operations accepted by the token admin commands + */ + +#define TOKEN_DISABLE 0x1 /* disable user account */ +#define TOKEN_ENABLE 0x2 /* enable user account */ +#define TOKEN_INITUSER 0x4 /* add/init user account */ +#define TOKEN_RMUSER 0x8 /* remove user account */ +#define TOKEN_UNLOCK 0x10 /* force unlock db record */ + +/* + * Flags for options to modify TOKEN_INITUSER + */ + +#define TOKEN_FORCEINIT 0x100 /* reinit existing account */ +#define TOKEN_GENSECRET 0x200 /* gen shared secret for token */ + +/* + * Structure describing different token cards + */ +struct token_types { + char *name; /* name of card */ + char *proper; /* proper name of card */ + char *db; /* path to database */ + char map[6]; /* how A-F map to decimal */ + int options; /* varios available options */ + u_int modes; /* available modes */ + u_int defmode; /* default mode (if none specified) */ +}; + +struct token_types *tt; /* what type we are running as now */ + +/* + * Options + */ +#define TOKEN_PHONE 0x0001 /* Allow phone number representation */ +#define TOKEN_HEXINIT 0x0002 /* Allow initialization in hex (and octal) */ + +/* + * Function prototypes for commands involving intimate DES knowledge + */ + +extern void tokenchallenge(char *, char *, int, char *); +extern int tokenverify(char *, char *, char *); +extern int tokenuserinit(int, char *, u_char *, u_int); +extern int token_init(char *); +extern u_int token_mode(char *); +extern char * token_getmode(u_int); diff --git a/libexec/login_token/tokendb.c b/libexec/login_token/tokendb.c new file mode 100644 index 00000000000..bfc021ac4aa --- /dev/null +++ b/libexec/login_token/tokendb.c @@ -0,0 +1,343 @@ +/* $OpenBSD: tokendb.c,v 1.1 2000/12/20 01:41:53 millert Exp $ */ + +/*- + * Copyright (c) 1995 Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Berkeley Software Design, + * Inc. + * 4. The name of Berkeley Software Design, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``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 BERKELEY SOFTWARE DESIGN, INC. 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. + * + * BSDI $From: tokendb.c,v 1.1 1996/08/26 20:13:10 prb Exp $ + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> + +#include <ctype.h> +#include <db.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <syslog.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "token.h" +#include "tokendb.h" + +static DB *tokendb; + +/* + * Static function prototypes + */ + +static int tokendb_open(void); +static void tokendb_close(void); + +/* + * Retrieve a user record from the token database file + */ + +int +tokendb_getrec(char *username, TOKENDB_Rec *tokenrec) +{ + DBT key; + DBT data; + int status = 0; + + key.data = username; + key.size = strlen(username) + 1; + memset(&data, 0, sizeof(data)); + + if (tokendb_open()) + return(-1); + + status = (tokendb->get)(tokendb, &key, &data, 0); + tokendb_close(); + + switch (status) { + case 1: + return(ENOENT); + case -1: + return(-1); + } + memcpy(tokenrec, data.data, sizeof(TOKENDB_Rec)); + if ((tokenrec->flags & TOKEN_USEMODES) == 0) + tokenrec->mode = tt->modes & ~TOKEN_RIM; + return (0); +} + +/* + * Put a user record to the token database file. + */ + +int +tokendb_putrec(char *username, TOKENDB_Rec *tokenrec) +{ + DBT key; + DBT data; + int status = 0; + + key.data = username; + key.size = strlen(username) + 1; + + if (tokenrec->mode) + tokenrec->flags |= TOKEN_USEMODES; + data.data = tokenrec; + data.size = sizeof(TOKENDB_Rec); + + if (!tokendb_open()) { + if (flock((tokendb->fd)(tokendb), LOCK_EX)) { + tokendb_close(); + return (-1); + } + status = (tokendb->put)(tokendb, &key, &data, 0); + } + tokendb_close(); + return (status); +} + +/* + * Remove a user record from the token database file. + */ + +int +tokendb_delrec(char *username) +{ + DBT key; + DBT data; + int status = 0; + + key.data = username; + key.size = strlen(username) + 1; + memset(&data, 0, sizeof(data)); + + if (!tokendb_open()) { + if (flock((tokendb->fd)(tokendb), LOCK_EX)) { + tokendb_close(); + return (-1); + } + status = (tokendb->del)(tokendb, &key, 0); + } + tokendb_close(); + return (status); +} + +/* + * Open the token database. In order to expedite access in + * heavily loaded conditions, we employ a N1 lock method. + * Updates should be brief, so all locks wait infinitely. + * Wait for a read (shared) lock as all updates read first. + */ + +static int +tokendb_open(void) +{ + int must_set_perms = 0; + struct stat statb; + + if (stat(tt->db, &statb) < 0) { + if (errno != ENOENT) + return (-1); + must_set_perms++; + } else { + if (statb.st_uid != 0 || statb.st_gid != 0) { +#ifdef PARANOID + printf("Authentication disabled\n"); + fflush(stdout); + syslog(LOG_ALERT, + "POTENTIAL COMPROMISE of %s. Owner was %d, " + "Group was %d", tt->db, statb.st_uid, statb.st_gid); + return (-1); +#else + must_set_perms++; +#endif + } + if ((statb.st_mode & 0777) != 0600) { +#ifdef PARANOID + printf("Authentication disabled\n"); + fflush(stdout); + syslog(LOG_ALERT, + "POTENTIAL COMPROMISE of %s. Mode was %o", + tt->db, statb.st_mode); + return (-1); +#else + must_set_perms++; +#endif + } + } + if (!(tokendb = + dbopen(tt->db, O_CREAT | O_RDWR, 0600, DB_BTREE, 0)) ) + return (-1); + + if (flock((tokendb->fd)(tokendb), LOCK_SH)) { + (tokendb->close)(tokendb); + return (-1); + } + if (must_set_perms && chown(tt->db, 0, 0)) + syslog(LOG_INFO, + "Can't set owner/group of %s errno=%m", tt->db); + + return (0); +} + +/* + * Close the token database. We are holding an unknown lock. + * Release it, then close the db. Since little can be done + * about errors, we ignore them. + */ + +static void +tokendb_close(void) +{ + (void)flock((tokendb->fd)(tokendb), LOCK_UN); + (tokendb->close)(tokendb); +} + +/* + * Retrieve the first user record from the database, leaving the + * database open for the next retrieval. If the march thru the + * the database is aborted before end-of-file, the caller should + * call tokendb_close to release the read lock. + */ + +int +tokendb_firstrec(int reverse_flag, TOKENDB_Rec *tokenrec) +{ + DBT key; + DBT data; + int status = 0; + + memset(&data, 0, sizeof(data)); + + if (!tokendb_open()) { + status = (tokendb->seq)(tokendb, &key, &data, + reverse_flag ? R_LAST : R_FIRST); + } + if (status) { + tokendb_close(); + return (status); + } + if (!data.data) { + tokendb_close(); + return (ENOENT); + } + memcpy(tokenrec, data.data, sizeof(TOKENDB_Rec)); + if ((tokenrec->flags & TOKEN_USEMODES) == 0) + tokenrec->mode = tt->modes & ~TOKEN_RIM; + return (0); +} + +/* + * Retrieve the next sequential user record from the database. Close + * the database only on end-of-file or error. + */ + + +int +tokendb_nextrec(int reverse_flag, TOKENDB_Rec *tokenrec) +{ + DBT key; + DBT data; + int status; + + memset(&data, 0, sizeof(data)); + + status = (tokendb->seq)(tokendb, &key, &data, + reverse_flag ? R_PREV : R_NEXT); + + if (status) { + tokendb_close(); + return (status); + } + if (!data.data) { + tokendb_close(); + return (ENOENT); + } + memcpy(tokenrec, data.data, sizeof(TOKENDB_Rec)); + if ((tokenrec->flags & TOKEN_USEMODES) == 0) + tokenrec->mode = tt->modes & ~TOKEN_RIM; + return (0); +} + +/* + * Retrieve and lock a user record. Since there are no facilities in + * BSD for record locking, we hack a bit lock into the user record. + */ + +int +tokendb_lockrec(char *username, TOKENDB_Rec *tokenrec, unsigned recflags) +{ + DBT key; + DBT data; + int status; + + key.data = username; + key.size = strlen(username) + 1; + memset(&data, 0, sizeof(data)); + + if (tokendb_open()) + return(-1); + + if (flock((tokendb->fd)(tokendb), LOCK_EX)) { + tokendb_close(); + return(-1); + } + switch ((tokendb->get)(tokendb, &key, &data, 0)) { + case 1: + tokendb_close(); + return (ENOENT); + case -1: + tokendb_close(); + return(-1); + } + memcpy(tokenrec, data.data, sizeof(TOKENDB_Rec)); + + if ((tokenrec->flags & TOKEN_LOCKED)||(tokenrec->flags & recflags)) { + tokendb_close(); + return(1); + } + data.data = tokenrec; + data.size = sizeof(TOKENDB_Rec); + + time(&tokenrec->lock_time); + tokenrec->flags |= recflags; + status = (tokendb->put)(tokendb, &key, &data, 0); + tokendb_close(); + if (status) + return(-1); + if ((tokenrec->flags & TOKEN_USEMODES) == 0) + tokenrec->mode = tt->modes & ~TOKEN_RIM; + + return(0); +} + diff --git a/libexec/login_token/tokendb.h b/libexec/login_token/tokendb.h new file mode 100644 index 00000000000..32a80985088 --- /dev/null +++ b/libexec/login_token/tokendb.h @@ -0,0 +1,80 @@ +/* $OpenBSD: tokendb.h,v 1.1 2000/12/20 01:41:53 millert Exp $ */ + +/*- + * Copyright (c) 1995 Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Berkeley Software Design, + * Inc. + * 4. The name of Berkeley Software Design, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``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 BERKELEY SOFTWARE DESIGN, INC. 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. + * + * BSDI $From: tokendb.h,v 1.1 1996/08/26 20:13:11 prb Exp $ + */ + +/* + * Structure defining a record for a user. All fields + * stored in ascii to facilitate backup/reconstruction. + * A null byte is required after the share secret field. + */ + +typedef struct { + char uname[L_cuserid]; /* user login name */ + char secret[16]; /* token shared secret */ + unsigned flags; /* record flags */ + unsigned mode; /* token mode flags */ + time_t lock_time; /* time of record lock */ + u_char rim[8]; /* reduced input mode */ + char reserved_char1[8]; + char reserved_char2[80]; +} TOKENDB_Rec; + +/* + * Record flag values + */ + +#define TOKEN_LOCKED 0x1 /* record locked for updating */ +#define TOKEN_ENABLED 0x2 /* user login method enabled */ +#define TOKEN_LOGIN 0x4 /* login in progress lock */ +#define TOKEN_USEMODES 0x8 /* use the mode field */ + +#define TOKEN_DECMODE 0x1 /* allow decimal results */ +#define TOKEN_HEXMODE 0x2 /* allow hex results */ +#define TOKEN_PHONEMODE 0x4 /* allow phone book results */ +#define TOKEN_RIM 0x8 /* reduced imput mode */ + +/* + * Function prototypes for routines which manipulate the + * database for the token. These routines have no knowledge + * of DES or encryption. However, they will manipulate the + * flags field of the database record with complete abandon. + */ + +extern int tokendb_delrec(char *); +extern int tokendb_getrec(char *, TOKENDB_Rec *); +extern int tokendb_putrec(char *, TOKENDB_Rec *); +extern int tokendb_firstrec(int, TOKENDB_Rec *); +extern int tokendb_nextrec(int, TOKENDB_Rec *); +extern int tokendb_lockrec(char *, TOKENDB_Rec *, unsigned); |