summaryrefslogtreecommitdiffstats
path: root/third_party/heimdal/appl/otp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/appl/otp')
-rw-r--r--third_party/heimdal/appl/otp/ChangeLog58
-rw-r--r--third_party/heimdal/appl/otp/Makefile.am15
-rw-r--r--third_party/heimdal/appl/otp/NTMakefile35
-rw-r--r--third_party/heimdal/appl/otp/otp.190
-rw-r--r--third_party/heimdal/appl/otp/otp.c371
-rw-r--r--third_party/heimdal/appl/otp/otp_locl.h56
-rw-r--r--third_party/heimdal/appl/otp/otpprint.182
-rw-r--r--third_party/heimdal/appl/otp/otpprint.c136
8 files changed, 843 insertions, 0 deletions
diff --git a/third_party/heimdal/appl/otp/ChangeLog b/third_party/heimdal/appl/otp/ChangeLog
new file mode 100644
index 0000000..76df17c
--- /dev/null
+++ b/third_party/heimdal/appl/otp/ChangeLog
@@ -0,0 +1,58 @@
+2006-10-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add man_MANS to EXTRA_DIST
+
+2005-05-29 Love Hörquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add LIB_roken as a explit dependency
+
+2003-09-03 Love Hörquist Åstrand <lha@it.su.se>
+
+ * otpprint.c: s/des_read_pw_string/UI_UTIL_read_pw_string/
+
+ * otp.c: s/des_read_pw_string/UI_UTIL_read_pw_string/
+
+2003-02-25 Love Hörquist Åstrand <lha@it.su.se>
+
+ * otp.c: remove \n from errx, from NetBSD
+
+2000-11-29 Johan Danielsson <joda@pdc.kth.se>
+
+ * otpprint.1: sort parameters and close a list
+
+ * otp.1: sort parameters and close a list
+
+1999-09-14 Assar Westerlund <assar@sics.se>
+
+ * otp.c (verify_user_otp): check return value from
+ des_read_pw_string
+
+Thu Apr 1 16:51:07 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * otpprint.c: use getarg
+
+ * otp.c: use getarg
+
+Thu Mar 18 12:08:58 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * Makefile.am: include Makefile.am.common
+
+Thu Mar 4 19:45:40 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * Makefile.am: DESTDIR
+
+Sat Feb 27 19:44:25 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * Makefile.am: add
+
+Sun Nov 22 10:32:50 1998 Assar Westerlund <assar@sics.se>
+
+ * otpprint.c: more braces
+
+ * Makefile.in (WFLAGS): set
+
+Sun Dec 21 09:31:30 1997 Assar Westerlund <assar@sics.se>
+
+ * otp.c (renew): don't set the OTP if the reading of the string
+ fails.
+
diff --git a/third_party/heimdal/appl/otp/Makefile.am b/third_party/heimdal/appl/otp/Makefile.am
new file mode 100644
index 0000000..d8e5d51
--- /dev/null
+++ b/third_party/heimdal/appl/otp/Makefile.am
@@ -0,0 +1,15 @@
+# $Id$
+
+include $(top_srcdir)/Makefile.am.common
+
+bin_PROGRAMS = otp otpprint
+bin_SUIDS = otp
+otp_SOURCES = otp.c otp_locl.h
+otp_LDADD = $(LIB_hcrypto) $(LIB_roken) $(top_builddir)/lib/otp/libotp.la
+otpprint_SOURCES = otpprint.c otp_locl.h
+
+otpprint_LDADD = $(LIB_hcrypto) $(LIB_roken) $(top_builddir)/lib/otp/libotp.la
+
+man_MANS = otp.1 otpprint.1
+
+EXTRA_DIST = NTMakefile $(man_MANS)
diff --git a/third_party/heimdal/appl/otp/NTMakefile b/third_party/heimdal/appl/otp/NTMakefile
new file mode 100644
index 0000000..6256309
--- /dev/null
+++ b/third_party/heimdal/appl/otp/NTMakefile
@@ -0,0 +1,35 @@
+########################################################################
+#
+# Copyright (c) 2009, Secure Endpoints 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:
+#
+# - 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.
+#
+# 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 HOLDER 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.
+#
+
+RELDIR=appl\otp
+
+!include ../../windows/NTMakefile.w32
+
diff --git a/third_party/heimdal/appl/otp/otp.1 b/third_party/heimdal/appl/otp/otp.1
new file mode 100644
index 0000000..8676948
--- /dev/null
+++ b/third_party/heimdal/appl/otp/otp.1
@@ -0,0 +1,90 @@
+.\" Copyright (c) 1996, 2000 Kungliga Tekniska Högskolan
+.\" (Royal Institute of Technology, Stockholm, Sweden).
+.\" 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. Neither the name of the Institute nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+.\"
+.\" $Id$
+.\"
+.Dd November 17, 1996
+.Dt OTP 1
+.Os KTH-KRB
+.Sh NAME
+.Nm otp
+.Nd manages one-time passwords
+.Sh SYNOPSIS
+.Nm otp
+.Op Fl dhlor
+.Op Fl f Ar algorithm
+.Op Fl u Ar user
+.Ar sequence-number
+.Ar seed
+.Sh DESCRIPTION
+The
+.Nm
+program initializes and updates your current series of one-time
+passwords (OTPs).
+.Pp
+Use this to set a new series of one-time passwords. Only perform this
+on the console or over an encrypted link as you will have to supply
+your pass-phrase. The other two parameters are
+.Ar sequence-number
+and
+.Ar seed .
+.Pp
+Options are:
+.Bl -tag -width Ds
+.It Fl d
+To delete a one-time password.
+.It Fl f
+Choose a different
+.Ar algorithm
+from the default md5. Pick any of: md4, md5, and sha.
+.It Fl h
+For getting a help message.
+.It Fl l
+List the current table of one-time passwords.
+.It Fl o
+To open (unlock) the otp-entry for a user.
+.It Fl r
+To renew a one-time password series. This operation can be performed
+over an potentially eavesdropped link because you do not supply the
+pass-phrase. First you need to supply the current one-time password
+and then the new one corresponding to the supplied
+.Ar sequence-number
+and
+.Ar seed .
+.It Fl u
+To choose a different
+.Ar user
+to set one-time passwords for. This only works when running
+.Nm
+as root.
+.El
+.Sh SEE ALSO
+.Xr otpprint 1
diff --git a/third_party/heimdal/appl/otp/otp.c b/third_party/heimdal/appl/otp/otp.c
new file mode 100644
index 0000000..deb7d30
--- /dev/null
+++ b/third_party/heimdal/appl/otp/otp.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 1995-1997, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+#include "otp_locl.h"
+#include <getarg.h>
+
+RCSID("$Id$");
+
+static int listp;
+static int deletep;
+static int openp;
+static int renewp;
+static char* alg_string;
+static char *user;
+static int version_flag;
+static int help_flag;
+
+struct getargs args[] = {
+ { "list", 'l', arg_flag, &listp, "list OTP status", NULL },
+ { "delete", 'd', arg_flag, &deletep, "delete OTP", NULL },
+ { "open", 'o', arg_flag, &openp, "open a locked OTP", NULL },
+ { "renew", 'r', arg_flag, &renewp, "securely renew OTP", NULL },
+ { "hash", 'f', arg_string, &alg_string,
+ "hash algorithm (md4, md5, or sha)", "algorithm"},
+ { "user", 'u', arg_string, &user,
+ "user other than current user (root only)", "user" },
+ { "version", 0, arg_flag, &version_flag, NULL, NULL },
+ { "help", 'h', arg_flag, &help_flag, NULL, NULL }
+};
+
+int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int code)
+{
+ arg_printusage(args, num_args, NULL, "[num seed]");
+ exit(code);
+}
+
+/*
+ * Renew the OTP for a user.
+ * The pass-phrase is not required (RFC 1938/8.0)
+ */
+
+static int
+renew (int argc, char **argv, OtpAlgorithm *alg, char *inuser)
+{
+ OtpContext newctx, *ctx;
+ char prompt[128];
+ char pw[64];
+ void *dbm;
+ int ret;
+
+ newctx.alg = alg;
+ newctx.user = inuser;
+ newctx.n = atoi (argv[0]);
+ strlcpy (newctx.seed, argv[1], sizeof(newctx.seed));
+ strlwr(newctx.seed);
+ snprintf (prompt, sizeof(prompt),
+ "[ otp-%s %u %s ]",
+ newctx.alg->name,
+ newctx.n,
+ newctx.seed);
+ if (UI_UTIL_read_pw_string (pw, sizeof(pw), prompt, 0) == 0 &&
+ otp_parse (newctx.key, pw, alg) == 0) {
+ ctx = &newctx;
+ ret = 0;
+ } else
+ return 1;
+
+ dbm = otp_db_open ();
+ if (dbm == NULL) {
+ warnx ("otp_db_open failed");
+ return 1;
+ }
+ otp_put (dbm, ctx);
+ otp_db_close (dbm);
+ return ret;
+}
+
+/*
+ * Return 0 if the user could enter the next OTP.
+ * I would rather have returned !=0 but it's shell-like here around.
+ */
+
+static int
+verify_user_otp(char *username)
+{
+ OtpContext ctx;
+ char passwd[OTP_MAX_PASSPHRASE + 1];
+ char ss[256];
+ char *prompt = NULL;
+
+ if (otp_challenge (&ctx, username, ss, sizeof(ss)) != 0) {
+ warnx("no otp challenge found for %s", username);
+ return 1;
+ }
+
+ if (asprintf(&prompt, "%s's %s Password: ", username, ss) == -1 ||
+ prompt == NULL)
+ err(1, "out of memory");
+ if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)) {
+ free(prompt);
+ return 1;
+ }
+ free(prompt);
+ return otp_verify_user (&ctx, passwd);
+}
+
+/*
+ * Set the OTP for a user
+ */
+
+static int
+set (int argc, char **argv, OtpAlgorithm *alg, char *inuser)
+{
+ void *db;
+ OtpContext ctx;
+ char pw[OTP_MAX_PASSPHRASE + 1];
+ int ret;
+ int i;
+
+ ctx.alg = alg;
+ ctx.user = strdup (inuser);
+ if (ctx.user == NULL)
+ err (1, "out of memory");
+
+ ctx.n = atoi (argv[0]);
+ strlcpy (ctx.seed, argv[1], sizeof(ctx.seed));
+ strlwr(ctx.seed);
+ do {
+ if (UI_UTIL_read_pw_string (pw, sizeof(pw), "Pass-phrase: ",
+ UI_UTIL_FLAG_VERIFY))
+ return 1;
+ if (strlen (pw) < OTP_MIN_PASSPHRASE)
+ printf ("Too short pass-phrase. Use at least %d characters\n",
+ OTP_MIN_PASSPHRASE);
+ } while(strlen(pw) < OTP_MIN_PASSPHRASE);
+ ctx.alg->init (ctx.key, pw, ctx.seed);
+ for (i = 0; i < ctx.n; ++i)
+ ctx.alg->next (ctx.key);
+ db = otp_db_open ();
+ if(db == NULL) {
+ free (ctx.user);
+ err (1, "otp_db_open failed");
+ }
+ ret = otp_put (db, &ctx);
+ otp_db_close (db);
+ free (ctx.user);
+ return ret;
+}
+
+/*
+ * Delete otp of user from the database
+ */
+
+static int
+delete_otp (int argc, char **argv, char *inuser)
+{
+ void *db;
+ OtpContext ctx;
+ int ret;
+
+ db = otp_db_open ();
+ if(db == NULL)
+ errx (1, "otp_db_open failed");
+
+ ctx.user = inuser;
+ ret = otp_delete(db, &ctx);
+ otp_db_close (db);
+ return ret;
+}
+
+/*
+ * Tell whether the user has an otp
+ */
+
+static int
+has_an_otp(char *inuser)
+{
+ void *db;
+ OtpContext ctx;
+ int ret;
+
+ db = otp_db_open ();
+ if(db == NULL) {
+ warnx ("otp_db_open failed");
+ return 0; /* if no db no otp! */
+ }
+
+ ctx.user = inuser;
+ ret = otp_simple_get(db, &ctx);
+
+ otp_db_close (db);
+ return !ret;
+}
+
+/*
+ * Get and print out the otp entry for some user
+ */
+
+static void
+print_otp_entry_for_name (void *db, char *inuser)
+{
+ OtpContext ctx;
+
+ ctx.user = inuser;
+ if (!otp_simple_get(db, &ctx)) {
+ fprintf(stdout,
+ "%s\totp-%s %d %s",
+ ctx.user, ctx.alg->name, ctx.n, ctx.seed);
+ if (ctx.lock_time)
+ fprintf(stdout,
+ "\tlocked since %s",
+ ctime(&ctx.lock_time));
+ else
+ fprintf(stdout, "\n");
+ }
+}
+
+static int
+open_otp (int argc, char **argv, char *inuser)
+{
+ void *db;
+ OtpContext ctx;
+ int ret;
+
+ db = otp_db_open ();
+ if (db == NULL)
+ errx (1, "otp_db_open failed");
+
+ ctx.user = inuser;
+ ret = otp_simple_get (db, &ctx);
+ if (ret == 0)
+ ret = otp_put (db, &ctx);
+ otp_db_close (db);
+ return ret;
+}
+
+/*
+ * Print otp entries for one or all users
+ */
+
+static int
+list_otps (int argc, char **argv, char *inuser)
+{
+ void *db;
+ struct passwd *pw;
+
+ db = otp_db_open ();
+ if(db == NULL)
+ errx (1, "otp_db_open failed");
+
+ if (inuser)
+ print_otp_entry_for_name(db, inuser);
+ else
+ /* scans all users... so as to get a deterministic order */
+ while ((pw = getpwent()))
+ print_otp_entry_for_name(db, pw->pw_name);
+
+ otp_db_close (db);
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ int defaultp = 0;
+ int uid = getuid();
+ OtpAlgorithm *alg = otp_find_alg (OTP_ALG_DEFAULT);
+ int optidx = 0;
+ char userbuf[128];
+
+ setprogname (argv[0]);
+ if(getarg(args, num_args, argc, argv, &optidx))
+ usage(1);
+ if(help_flag)
+ usage(0);
+ if(version_flag) {
+ print_version(NULL);
+ exit(0);
+ }
+
+ if(deletep && uid != 0)
+ errx (1, "Only root can delete OTPs");
+ if(alg_string) {
+ alg = otp_find_alg (alg_string);
+ if (alg == NULL)
+ errx (1, "Unknown algorithm: %s", alg_string);
+ }
+ if (user && uid != 0)
+ errx (1, "Only root can use `-u'");
+ argc -= optidx;
+ argv += optidx;
+
+ if (!(listp || deletep || renewp || openp))
+ defaultp = 1;
+
+ if ( listp + deletep + renewp + defaultp + openp != 1)
+ usage(1); /* one of -d or -l or -r or none */
+
+ if(deletep || openp || listp) {
+ if(argc != 0)
+ errx(1, "delete, open, and list requires no arguments");
+ } else {
+ if(argc != 2)
+ errx(1, "setup, and renew requires `num', and `seed'");
+ }
+ if (listp)
+ return list_otps (argc, argv, user);
+
+ if (user == NULL) {
+ user = roken_get_username(userbuf, sizeof(userbuf));
+ if (user == NULL)
+ err (1, "You don't exist");
+ }
+
+ /*
+ * users other that root must provide the next OTP to update the sequence.
+ * it avoids someone to use a pending session to change an OTP sequence.
+ * see RFC 1938/8.0.
+ */
+ if (uid != 0 && (defaultp || renewp)) {
+ if (!has_an_otp(user)) {
+ errx (1, "Only root can set an initial OTP");
+ } else { /* Check the next OTP (RFC 1938/8.0: SHOULD) */
+ if (verify_user_otp(user) != 0) {
+ errx (1, "User authentication failed");
+ }
+ }
+ }
+
+ if (deletep)
+ return delete_otp (argc, argv, user);
+ else if (renewp)
+ return renew (argc, argv, alg, user);
+ else if (openp)
+ return open_otp (argc, argv, user);
+ else
+ return set (argc, argv, alg, user);
+}
diff --git a/third_party/heimdal/appl/otp/otp_locl.h b/third_party/heimdal/appl/otp/otp_locl.h
new file mode 100644
index 0000000..76f0ac4
--- /dev/null
+++ b/third_party/heimdal/appl/otp/otp_locl.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <roken.h>
+#include <err.h>
+#include "crypto-headers.h" /* for des_read_pw_string */
+#include <otp.h>
diff --git a/third_party/heimdal/appl/otp/otpprint.1 b/third_party/heimdal/appl/otp/otpprint.1
new file mode 100644
index 0000000..8045933
--- /dev/null
+++ b/third_party/heimdal/appl/otp/otpprint.1
@@ -0,0 +1,82 @@
+.\" Copyright (c) 1996, 2000 - 2001 Kungliga Tekniska Högskolan
+.\" (Royal Institute of Technology, Stockholm, Sweden).
+.\" 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. Neither the name of the Institute nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+.\"
+.\" $Id$
+.\"
+.Dd November 17, 1996
+.Dt OTP 1
+.Os KTH-KRB
+.Sh NAME
+.Nm otpprint
+.Nd print lists of one-time passwords
+.Sh SYNOPSIS
+.Nm otp
+.Op Fl n Ar count
+.Op Fl e
+.Op Fl h
+.Op Fl f Ar algorithm
+.Ar sequence-number
+.Ar seed
+.Sh DESCRIPTION
+The
+.Nm
+program prints lists of OTPs.
+.Pp
+Use this to print out a series of one-time passwords. You will have
+to supply the
+.Ar sequence number
+and the
+.Ar seed
+as arguments and then the program will prompt you for your pass-phrase.
+.Pp
+There are several different print formats. The default is to print
+each password with six short english words.
+.Pp
+Options are:
+.Bl -tag -width Ds
+.It Fl e
+Print the passwords in ``extended'' format. In this format a prefix
+that says ``hex:'' or ``word:'' is included.
+.It Fl f
+To choose a different
+.Ar algorithm
+from the default md5. Pick any of: md4, md5, and sha.
+.It Fl h
+Print the passwords in hex.
+.It Fl n
+Print
+.Ar count
+one-time passwords, starting at
+.Ar sequence-number
+and going backwards. The default is 10.
+.El
+.Sh SEE ALSO
+.Xr otp 1
diff --git a/third_party/heimdal/appl/otp/otpprint.c b/third_party/heimdal/appl/otp/otpprint.c
new file mode 100644
index 0000000..1c9c339
--- /dev/null
+++ b/third_party/heimdal/appl/otp/otpprint.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+#include "otp_locl.h"
+#include <getarg.h>
+
+RCSID("$Id$");
+
+static int extendedp;
+static int count = 10;
+static int hexp;
+static char* alg_string;
+static int version_flag;
+static int help_flag;
+
+struct getargs args[] = {
+ { "extended", 'e', arg_flag, &extendedp, "print keys in extended format",
+ NULL },
+ { "count", 'n', arg_integer, &count, "number of keys to print", NULL },
+ { "hexadecimal", 'h', arg_flag, &hexp, "output in hexadecimal", NULL },
+ { "hash", 'f', arg_string, &alg_string,
+ "hash algorithm (md4, md5, or sha)", "algorithm"},
+ { "version", 0, arg_flag, &version_flag, NULL, NULL },
+ { "help", 0, arg_flag, &help_flag, NULL, NULL }
+};
+
+int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int code)
+{
+ arg_printusage(args, num_args, NULL, "num seed");
+ exit(code);
+}
+
+static int
+print (int argc,
+ char **argv,
+ int incount,
+ OtpAlgorithm *alg,
+ void (*print_fn)(OtpKey, char *, size_t))
+{
+ char pw[64];
+ OtpKey key;
+ int n;
+ int i;
+ char *seed;
+
+ if (argc != 2)
+ usage (1);
+ n = atoi(argv[0]);
+ seed = argv[1];
+ if (UI_UTIL_read_pw_string (pw, sizeof(pw), "Pass-phrase: ", 0))
+ return 1;
+ alg->init (key, pw, seed);
+ for (i = 0; i < n; ++i) {
+ char s[64];
+
+ alg->next (key);
+ if (i >= n - incount) {
+ (*print_fn)(key, s, sizeof(s));
+ printf ("%d: %s\n", i + 1, s);
+ }
+ }
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ int optidx = 0;
+ void (*fn)(OtpKey, char *, size_t);
+ OtpAlgorithm *alg = otp_find_alg (OTP_ALG_DEFAULT);
+
+ setprogname (argv[0]);
+ if(getarg(args, num_args, argc, argv, &optidx))
+ usage(1);
+ if(help_flag)
+ usage(0);
+ if(version_flag) {
+ print_version(NULL);
+ exit(0);
+ }
+
+ if(alg_string) {
+ alg = otp_find_alg (alg_string);
+ if (alg == NULL)
+ errx(1, "Unknown algorithm: %s", alg_string);
+ }
+ argc -= optidx;
+ argv += optidx;
+
+ if (hexp) {
+ if (extendedp)
+ fn = otp_print_hex_extended;
+ else
+ fn = otp_print_hex;
+ } else {
+ if (extendedp)
+ fn = otp_print_stddict_extended;
+ else
+ fn = otp_print_stddict;
+ }
+
+ return print (argc, argv, count, alg, fn);
+}