View | Details | Raw Unified | Return to bug 1439
Collapse All | Expand All

(-)openssh-4.7p1/Makefile.in (+1 lines)
Lines 79-88 Link Here
79
SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
79
SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
80
	sshpty.o sshlogin.o servconf.o serverloop.o \
80
	sshpty.o sshlogin.o servconf.o serverloop.o \
81
	auth.o auth1.o auth2.o auth-options.o session.o \
81
	auth.o auth1.o auth2.o auth-options.o session.o \
82
	auth-chall.o auth2-chall.o groupaccess.o \
82
	auth-chall.o auth2-chall.o groupaccess.o \
83
	auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
83
	auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
84
	auth-vtoken.o \
84
	auth2-none.o auth2-passwd.o auth2-pubkey.o \
85
	auth2-none.o auth2-passwd.o auth2-pubkey.o \
85
	monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
86
	monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
86
	auth-krb5.o \
87
	auth-krb5.o \
87
	auth2-gss.o gss-serv.o gss-serv-krb5.o \
88
	auth2-gss.o gss-serv.o gss-serv-krb5.o \
88
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
89
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
(-)openssh-4.7p1/config.h.in (+3 lines)
Lines 1222-1231 Link Here
1222
#undef SIZEOF_SHORT_INT
1222
#undef SIZEOF_SHORT_INT
1223
1223
1224
/* Define if you want S/Key support */
1224
/* Define if you want S/Key support */
1225
#undef SKEY
1225
#undef SKEY
1226
1226
1227
/* Define if you want Virtual Token support */
1228
#undef USE_VTOKEN
1229
1227
/* Define if your skeychallenge() function takes 4 arguments (NetBSD) */
1230
/* Define if your skeychallenge() function takes 4 arguments (NetBSD) */
1228
#undef SKEYCHALLENGE_4ARG
1231
#undef SKEYCHALLENGE_4ARG
1229
1232
1230
/* Define if you want smartcard support */
1233
/* Define if you want smartcard support */
1231
#undef SMARTCARD
1234
#undef SMARTCARD
(-)openssh-4.7p1/configure.ac (+16 lines)
Lines 1091-1100 Link Here
1091
        		)
1091
        		)
1092
		fi
1092
		fi
1093
	]
1093
	]
1094
)
1094
)
1095
1095
1096
# Check whether user wants Calc support
1097
VTOKEN_MSG="no"
1098
AC_ARG_WITH(vtoken,
1099
	[  --with-vtoken      Enable Virtual Token support],
1100
	[
1101
		if test "x$withval" != "xno" ; then
1102
1103
			AC_DEFINE(USE_VTOKEN, 1, [Define if you want Virtual Token support])
1104
			VTOKEN_MSG="yes"
1105
1106
			AC_MSG_CHECKING([for Virtual Token support])
1107
		fi
1108
	]
1109
)
1110
1096
# Check whether user wants TCP wrappers support
1111
# Check whether user wants TCP wrappers support
1097
TCPW_MSG="no"
1112
TCPW_MSG="no"
1098
AC_ARG_WITH(tcp-wrappers,
1113
AC_ARG_WITH(tcp-wrappers,
1099
	[  --with-tcp-wrappers[[=PATH]] Enable tcpwrappers support (optionally in PATH)],
1114
	[  --with-tcp-wrappers[[=PATH]] Enable tcpwrappers support (optionally in PATH)],
1100
	[
1115
	[
Lines 4029-4038 Link Here
4029
echo "                   OSF SIA support: $SIA_MSG"
4044
echo "                   OSF SIA support: $SIA_MSG"
4030
echo "                 KerberosV support: $KRB5_MSG"
4045
echo "                 KerberosV support: $KRB5_MSG"
4031
echo "                   SELinux support: $SELINUX_MSG"
4046
echo "                   SELinux support: $SELINUX_MSG"
4032
echo "                 Smartcard support: $SCARD_MSG"
4047
echo "                 Smartcard support: $SCARD_MSG"
4033
echo "                     S/KEY support: $SKEY_MSG"
4048
echo "                     S/KEY support: $SKEY_MSG"
4049
echo "             Virtual Token support: $VTOKEN_MSG"
4034
echo "              TCP Wrappers support: $TCPW_MSG"
4050
echo "              TCP Wrappers support: $TCPW_MSG"
4035
echo "              MD5 password support: $MD5_MSG"
4051
echo "              MD5 password support: $MD5_MSG"
4036
echo "                   libedit support: $LIBEDIT_MSG"
4052
echo "                   libedit support: $LIBEDIT_MSG"
4037
echo "  Solaris process contract support: $SPC_MSG"
4053
echo "  Solaris process contract support: $SPC_MSG"
4038
echo "       IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
4054
echo "       IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
(-)openssh-4.7p1/auth2-chall.c (-3 / +14 lines)
Lines 57-66 Link Here
57
extern KbdintDevice sshpam_device;
57
extern KbdintDevice sshpam_device;
58
#endif
58
#endif
59
#ifdef SKEY
59
#ifdef SKEY
60
extern KbdintDevice skey_device;
60
extern KbdintDevice skey_device;
61
#endif
61
#endif
62
#ifdef USE_VTOKEN
63
extern KbdintDevice vtoken_device;
64
#endif
62
#endif
65
#endif
63
66
64
KbdintDevice *devices[] = {
67
KbdintDevice *devices[] = {
65
#ifdef BSD_AUTH
68
#ifdef BSD_AUTH
66
	&bsdauth_device,
69
	&bsdauth_device,
Lines 69-78 Link Here
69
	&sshpam_device,
72
	&sshpam_device,
70
#endif
73
#endif
71
#ifdef SKEY
74
#ifdef SKEY
72
	&skey_device,
75
	&skey_device,
73
#endif
76
#endif
77
#ifdef USE_VTOKEN
78
	&vtoken_device,
79
#endif
74
#endif
80
#endif
75
	NULL
81
	NULL
76
};
82
};
77
83
78
typedef struct KbdintAuthctxt KbdintAuthctxt;
84
typedef struct KbdintAuthctxt KbdintAuthctxt;
Lines 88-98 Link Here
88
void
94
void
89
remove_kbdint_device(const char *devname)
95
remove_kbdint_device(const char *devname)
90
{
96
{
91
	int i, j;
97
	int i, j;
92
98
93
	for (i = 0; devices[i] != NULL; i++)
94
		if (strcmp(devices[i]->name, devname) == 0) {
99
		if (strcmp(devices[i]->name, devname) == 0) {
95
			for (j = i; devices[j] != NULL; j++)
100
			for (j = i; devices[j] != NULL; j++)
96
				devices[j] = devices[j+1];
101
				devices[j] = devices[j+1];
97
			i--;
102
			i--;
98
		}
103
		}
Lines 193-203 Link Here
193
	    authctxt->user ? authctxt->user : "<nouser>",
198
	    authctxt->user ? authctxt->user : "<nouser>",
194
	    devs ? devs : "<no devs>");
199
	    devs ? devs : "<no devs>");
195
200
196
	if (authctxt->user == NULL || !devs)
201
	if (authctxt->user == NULL || !devs)
197
		return 0;
202
		return 0;
198
	if (authctxt->kbdintctxt == NULL)
203
	if (authctxt->kbdintctxt == NULL) 
199
		authctxt->kbdintctxt = kbdint_alloc(devs);
204
		authctxt->kbdintctxt = kbdint_alloc(devs);
200
	return auth2_challenge_start(authctxt);
205
	return auth2_challenge_start(authctxt);
201
}
206
}
202
207
203
/* unregister kbd-int callbacks and context */
208
/* unregister kbd-int callbacks and context */
Lines 350-360 Link Here
350
}
355
}
351
356
352
void
357
void
353
privsep_challenge_enable(void)
358
privsep_challenge_enable(void)
354
{
359
{
355
#if defined(BSD_AUTH) || defined(USE_PAM) || defined(SKEY)
360
#if defined(BSD_AUTH) || defined(USE_PAM) || defined(SKEY) || defined(USE_VTOKEN)
356
	int n = 0;
361
	int n = 0;
357
#endif
362
#endif
358
#ifdef BSD_AUTH
363
#ifdef BSD_AUTH
359
	extern KbdintDevice mm_bsdauth_device;
364
	extern KbdintDevice mm_bsdauth_device;
360
#endif
365
#endif
Lines 362-378 Link Here
362
	extern KbdintDevice mm_sshpam_device;
367
	extern KbdintDevice mm_sshpam_device;
363
#endif
368
#endif
364
#ifdef SKEY
369
#ifdef SKEY
365
	extern KbdintDevice mm_skey_device;
370
	extern KbdintDevice mm_skey_device;
366
#endif
371
#endif
372
#ifdef USE_VTOKEN
373
	extern KbdintDevice mm_vtoken_device;
374
#endif
367
375
368
#ifdef BSD_AUTH
376
#ifdef BSD_AUTH
369
	devices[n++] = &mm_bsdauth_device;
377
	devices[n++] = &mm_bsdauth_device;
370
#else
378
#else
371
#ifdef USE_PAM
379
#ifdef USE_PAM
372
	devices[n++] = &mm_sshpam_device;
380
	devices[n++] = &mm_sshpam_device;
373
#endif
381
#endif
374
#ifdef SKEY
382
#ifdef SKEY
375
	devices[n++] = &mm_skey_device;
383
	devices[n++] = &mm_skey_device;
376
#endif
384
#endif
385
#ifdef USE_VTOKEN
386
	devices[n++] = &mm_vtoken_device;
387
#endif
377
#endif
388
#endif
378
}
389
}
(-)openssh-4.7p1/auth.h (+4 lines)
Lines 69-78 Link Here
69
	char		*krb5_ticket_file;
69
	char		*krb5_ticket_file;
70
	char		*krb5_ccname;
70
	char		*krb5_ccname;
71
#endif
71
#endif
72
	Buffer		*loginmsg;
72
	Buffer		*loginmsg;
73
	void		*methoddata;
73
	void		*methoddata;
74
	char		*vtoken;
74
};
75
};
75
/*
76
/*
76
 * Every authentication method has to handle authentication requests for
77
 * Every authentication method has to handle authentication requests for
77
 * non-existing users, or for users that are not allowed to login. In this
78
 * non-existing users, or for users that are not allowed to login. In this
78
 * case 'valid' is set to 0, but 'user' points to the username requested by
79
 * case 'valid' is set to 0, but 'user' points to the username requested by
Lines 153-162 Link Here
153
void	auth2_challenge_stop(Authctxt *);
154
void	auth2_challenge_stop(Authctxt *);
154
int	bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
155
int	bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
155
int	bsdauth_respond(void *, u_int, char **);
156
int	bsdauth_respond(void *, u_int, char **);
156
int	skey_query(void *, char **, char **, u_int *, char ***, u_int **);
157
int	skey_query(void *, char **, char **, u_int *, char ***, u_int **);
157
int	skey_respond(void *, u_int, char **);
158
int	skey_respond(void *, u_int, char **);
159
int	calc_challenge(Authctxt *);
160
int	calc_auth(Authctxt *);
161
int	calc_send(char *, char *, char *);
158
162
159
int	allowed_user(struct passwd *);
163
int	allowed_user(struct passwd *);
160
struct passwd * getpwnamallow(const char *user);
164
struct passwd * getpwnamallow(const char *user);
161
165
162
char	*get_challenge(Authctxt *);
166
char	*get_challenge(Authctxt *);
(-)openssh-4.7p1/auth-vtoken.c (+188 lines)
Line 0 Link Here
1
/* $OpenBSD: auth-vtoken.c,v 0.5 2008/02/04 07:55:00 pgsery Exp $ */
2
/*
3
 * Copyright (c) 2008 Paul Sery.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
/* This code was derived from Markus Friedl's auth-skey.c and
27
	Daniel B. Cid's Ossec/sendmail.c */
28
29
#include "includes.h"
30
31
#include <sys/types.h>
32
33
#include <string.h>
34
#include <stdarg.h>
35
36
#include "xmalloc.h"
37
#include "packet.h"
38
#include "log.h"
39
#include "key.h"
40
#include "hostfile.h"
41
#include "auth.h"
42
#include "buffer.h"
43
#ifdef GSSAPI
44
#include "ssh-gss.h"
45
#endif
46
#include "servconf.h"
47
#include "uidswap.h"
48
#include "monitor_wrap.h"
49
50
#include <netinet/in.h>
51
#include <netdb.h>
52
#include <arpa/inet.h>
53
#include <sys/socket.h>
54
#include <sys/types.h>  
55
#include <string.h>
56
#include <stdarg.h>
57
#include <unistd.h>     
58
#include "includes.h"   
59
#include "log.h"
60
61
#define TIME_FRAME 30
62
63
/* import */
64
extern ServerOptions options;
65
66
int
67
get_time(void)
68
{
69
        int secs;
70
        time_t now;
71
        struct tm *its;
72
73
        /* use time as counter */
74
        /* construct counter from minutes and seconds */
75
        now = time(NULL);
76
        its = localtime(&now);
77
        /* counter 60*60=3600 */
78
        secs = its->tm_min*60 + its->tm_sec;
79
80
        return(secs);
81
}
82
83
int
84
calculate_secret(int secret, int pin, int count)
85
{
86
        int challenge;
87
88
        /* user calculable challenge */
89
90
        /* !!! proof-of-concept calculation !!! */
91
	/* advantage: you can calculate the secret with paper 
92
		and pencil or simple calculator
93
	   advantage: you can build a simple cell phone or pda 
94
		app to perform this function
95
	   disadvantage: the unknowns can be brute-forced if the 
96
		challenge is intercepted */
97
        challenge = (secret * count) % pin;
98
99
        return(challenge);
100
}
101
102
static int
103
check_user_response(int user_response)
104
{
105
        int i, j=0, secs, curr_time, serv_chall, sec1, sec2;
106
        int authenticated=0, frame=TIME_FRAME, ignore[TIME_FRAME*2];
107
        char *user;
108
109
        /* get the user's secrets */
110
        for (i=0; options.vtoken_users[i] != NULL; i++) {
111
                user=strtok(options.vtoken_users[i],":");
112
                sec1=atoi(strtok(NULL,":"));
113
                sec2=atoi(strtok(NULL,":"));
114
                debug("get user secrets %s: %d %d",user,sec1,sec2);
115
        }
116
117
        /* calculate solutions, for a given time frame, using user's secrets */
118
        curr_time = get_time();
119
        for (i=-frame; i<=frame; i++) {
120
                secs = curr_time + i;
121
                serv_chall = calculate_secret(sec1, sec2, secs);
122
123
                /* compare user and server solutions */
124
                if (serv_chall == user_response) {
125
                        authenticated=1;
126
                        ignore[j++] = serv_chall;
127
                        break;
128
                } 
129
        }
130
131
        return authenticated;
132
}
133
134
static void *
135
vtoken_init_ctx(Authctxt *authctxt)
136
{
137
        return authctxt;
138
}
139
140
int
141
vtoken_query(void *ctx, char **name, char **infotxt,
142
    u_int* numprompts, char ***prompts, u_int **echo_on)
143
{
144
        *name = xstrdup("");
145
        *infotxt = xstrdup("");
146
        *numprompts = 1;
147
        *prompts = xcalloc(*numprompts, sizeof(char *));
148
        *echo_on = xcalloc(*numprompts, sizeof(u_int));
149
150
        xasprintf(*prompts, "Enter calculated secret:");
151
152
        return 0;
153
}
154
155
int
156
vtoken_respond(void *ctx, u_int numresponses, char **responses)
157
{
158
	Authctxt *authctxt = ctx;
159
160
	if (authctxt->valid && numresponses == 1 )
161
		if (check_user_response(atoi(responses[0])))
162
			return 0;
163
	return -1;
164
}
165
166
static void
167
vtoken_free_ctx(void *ctx)
168
{
169
	Authctxt *authctx = ctx;
170
171
	authctx->vtoken = NULL;
172
}
173
174
KbdintDevice vtoken_device = {
175
        "vtoken",
176
        vtoken_init_ctx,
177
	vtoken_query,
178
	vtoken_respond,
179
        vtoken_free_ctx
180
};
181
182
KbdintDevice mm_vtoken_device = {
183
	"vtoken",
184
	vtoken_init_ctx,
185
	mm_vtoken_query,
186
	mm_vtoken_respond,
187
	vtoken_free_ctx
188
};
(-)openssh-4.7p1/monitor.c (-8 / +36 lines)
Lines 156-165 Link Here
156
int mm_answer_pam_query(int, Buffer *);
156
int mm_answer_pam_query(int, Buffer *);
157
int mm_answer_pam_respond(int, Buffer *);
157
int mm_answer_pam_respond(int, Buffer *);
158
int mm_answer_pam_free_ctx(int, Buffer *);
158
int mm_answer_pam_free_ctx(int, Buffer *);
159
#endif
159
#endif
160
160
161
#ifdef USE_VTOKEN
162
int mm_answer_vtoken_query(int, Buffer *);
163
int mm_answer_vtoken_respond(int, Buffer *);
164
#endif
165
161
#ifdef GSSAPI
166
#ifdef GSSAPI
162
int mm_answer_gss_setup_ctx(int, Buffer *);
167
int mm_answer_gss_setup_ctx(int, Buffer *);
163
int mm_answer_gss_accept_ctx(int, Buffer *);
168
int mm_answer_gss_accept_ctx(int, Buffer *);
164
int mm_answer_gss_userok(int, Buffer *);
169
int mm_answer_gss_userok(int, Buffer *);
165
int mm_answer_gss_checkmic(int, Buffer *);
170
int mm_answer_gss_checkmic(int, Buffer *);
Lines 223-232 Link Here
223
#endif
228
#endif
224
#ifdef SKEY
229
#ifdef SKEY
225
    {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
230
    {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
226
    {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
231
    {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
227
#endif
232
#endif
233
#ifdef USE_VTOKEN
234
    {MONITOR_REQ_VTOKENQUERY, MON_ISAUTH, mm_answer_vtoken_query},
235
    {MONITOR_REQ_VTOKENRESPOND, MON_AUTH, mm_answer_vtoken_respond},
236
#endif
228
    {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
237
    {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
229
    {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
238
    {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
230
#ifdef GSSAPI
239
#ifdef GSSAPI
231
    {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
240
    {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
232
    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
241
    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
Lines 264-273 Link Here
264
#endif
273
#endif
265
#ifdef SKEY
274
#ifdef SKEY
266
    {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
275
    {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
267
    {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
276
    {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
268
#endif
277
#endif
278
#ifdef USE_VTOKEN
279
    {MONITOR_REQ_VTOKENQUERY, MON_ISAUTH, mm_answer_vtoken_query},
280
    {MONITOR_REQ_VTOKENRESPOND, MON_AUTH, mm_answer_vtoken_respond},
281
#endif
269
#ifdef USE_PAM
282
#ifdef USE_PAM
270
    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
283
    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
271
    {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
284
    {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
272
    {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
285
    {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
273
    {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
286
    {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
Lines 810-842 Link Here
810
	debug3("%s: sending challenge success: %u", __func__, success);
823
	debug3("%s: sending challenge success: %u", __func__, success);
811
	mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m);
824
	mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m);
812
825
813
	return (0);
826
	return (0);
814
}
827
}
828
#endif
815
829
830
#ifdef USE_VTOKEN
816
int
831
int
817
mm_answer_skeyrespond(int sock, Buffer *m)
832
mm_answer_vtoken_query(int sock, Buffer *m)
833
{
834
	char challenge[1024];
835
	u_int success=1;
836
837
	buffer_clear(m);
838
	buffer_put_int(m, success);
839
	if (success)
840
		buffer_put_cstring(m, challenge);
841
842
	debug3("%s: sending challenge success: %u", __func__, success);
843
844
	mm_request_send(sock, MONITOR_ANS_VTOKENQUERY, m);
845
846
	return (0);
847
}
848
849
int
850
mm_answer_vtoken_respond(int sock, Buffer *m)
818
{
851
{
819
	char *response;
852
	char *response;
820
	int authok;
853
	int authok;
821
854
822
	response = buffer_get_string(m, NULL);
855
	response = buffer_get_string(m, NULL);
823
856
824
	authok = (options.challenge_response_authentication &&
825
	    authctxt->valid &&
826
	    skey_haskey(authctxt->pw->pw_name) == 0 &&
827
	    skey_passcheck(authctxt->pw->pw_name, response) != -1);
828
829
	xfree(response);
857
	xfree(response);
830
858
831
	buffer_clear(m);
859
	buffer_clear(m);
832
	buffer_put_int(m, authok);
860
	buffer_put_int(m, authok);
833
861
834
	debug3("%s: sending authenticated: %d", __func__, authok);
862
	debug3("%s: sending authenticated: %d", __func__, authok);
835
	mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m);
863
	mm_request_send(sock, MONITOR_ANS_VTOKENRESPOND, m);
836
864
837
	auth_method = "skey";
865
	auth_method = "vtoken";
838
866
839
	return (authok != 0);
867
	return (authok != 0);
840
}
868
}
841
#endif
869
#endif
842
870
(-)openssh-4.7p1/monitor.h (+2 lines)
Lines 37-46 Link Here
37
	MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
37
	MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
38
	MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY,
38
	MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY,
39
	MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
39
	MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
40
	MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
40
	MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
41
	MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND,
41
	MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND,
42
	MONITOR_REQ_VTOKENQUERY, MONITOR_ANS_VTOKENQUERY,
43
	MONITOR_REQ_VTOKENRESPOND, MONITOR_ANS_VTOKENRESPOND,
42
	MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
44
	MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
43
	MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
45
	MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
44
	MONITOR_REQ_KEYEXPORT,
46
	MONITOR_REQ_KEYEXPORT,
45
	MONITOR_REQ_PTY, MONITOR_ANS_PTY,
47
	MONITOR_REQ_PTY, MONITOR_ANS_PTY,
46
	MONITOR_REQ_PTYCLEANUP,
48
	MONITOR_REQ_PTYCLEANUP,
(-)openssh-4.7p1/monitor_wrap.c (-3 / +136 lines)
Lines 817-836 Link Here
817
{
817
{
818
	Buffer m;
818
	Buffer m;
819
	u_int i;
819
	u_int i;
820
	int ret;
820
	int ret;
821
821
822
	debug3("%s", __func__);
822
	debug2("%s", __func__);
823
	buffer_init(&m);
823
	buffer_init(&m);
824
	buffer_put_int(&m, num);
824
	buffer_put_int(&m, num);
825
	for (i = 0; i < num; ++i)
825
	for (i = 0; i < num; ++i)
826
		buffer_put_cstring(&m, resp[i]);
826
		buffer_put_cstring(&m, resp[i]);
827
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
827
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
828
	debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
828
	debug2("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
829
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
829
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
830
	ret = buffer_get_int(&m);
830
	ret = buffer_get_int(&m);
831
	debug3("%s: pam_respond returned %d", __func__, ret);
831
	debug2("%s: pam_respond returned %d", __func__, ret);
832
	buffer_free(&m);
832
	buffer_free(&m);
833
	return (ret);
833
	return (ret);
834
}
834
}
835
835
836
void
836
void
Lines 1007-1016 Link Here
1007
1007
1008
	return ((authok == 0) ? -1 : 0);
1008
	return ((authok == 0) ? -1 : 0);
1009
}
1009
}
1010
#endif /* SKEY */
1010
#endif /* SKEY */
1011
1011
1012
#ifdef USE_VTOKEN
1013
1014
#define VTOKEN_TIME_FRAME 30
1015
1016
int
1017
mm_get_time(void)
1018
{
1019
        int secs;
1020
        time_t now;
1021
        struct tm *its;
1022
1023
        /* use time as counter */
1024
        now = time(NULL);
1025
        its = localtime(&now);
1026
        /* counter 60*60=3600 */
1027
        secs = its->tm_min*60 + its->tm_sec;
1028
1029
        return(secs);
1030
}
1031
1032
int
1033
mm_calculate_challenge(int secret, int pin, int count)
1034
{
1035
        int challenge;
1036
1037
        /* user calculable challenge */
1038
1039
        /* !!! proof-of-concept !!! */
1040
        /* this equation would be easy to brute-force if the
1041
                challenge is intercepted */
1042
	challenge = (secret * count) % pin;
1043
1044
        return(challenge);
1045
}
1046
1047
static int
1048
mm_check_user_response(int c_entry)
1049
{
1050
        int i, j=0, secs, curr_time, s_entry, sec1, sec2;
1051
        int authenticated=0, time_frame=VTOKEN_TIME_FRAME, ignore[VTOKEN_TIME_FRAME*2];
1052
        char *user;
1053
1054
        /* get the user's secrets */
1055
        for (i=0; options.vtoken_users[i] != NULL; i++) {
1056
                user=strtok(options.vtoken_users[i],":");
1057
                sec1=atoi(strtok(NULL,":"));
1058
                sec2=atoi(strtok(NULL,":"));
1059
                debug("%s: %s secrets %d,%d",__func__,user,sec1,sec2);
1060
        }
1061
1062
        /* calculate solutions, for a given time frame, using user's secrets */
1063
        curr_time = mm_get_time();
1064
        for (i=-time_frame; i<=time_frame; i++) {
1065
                secs = curr_time + i;
1066
                s_entry = mm_calculate_challenge(sec1, sec2, secs);
1067
1068
                /* compare user and server solutions */
1069
                if (s_entry == c_entry) {
1070
                        authenticated=1;
1071
                        ignore[j++] = s_entry;
1072
                        break;
1073
                } 
1074
        }
1075
1076
        return authenticated;
1077
}
1078
1079
int 
1080
mm_vtoken_query(void *ctx, char **name, char **infotxt,
1081
   u_int *numprompts, char ***prompts, u_int **echo_on)
1082
{
1083
	Buffer m;
1084
	u_int success;
1085
	char *challenge;
1086
1087
	buffer_init(&m);
1088
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_VTOKENQUERY, &m);
1089
1090
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_VTOKENQUERY,
1091
	    &m);
1092
	success = buffer_get_int(&m);
1093
	if (success == 0) {
1094
		debug3("%s: no challenge", __func__);
1095
		buffer_free(&m);
1096
		return (-1);
1097
	}
1098
1099
	/* Get the challenge, and format the response */
1100
	challenge  = buffer_get_string(&m, NULL);
1101
	buffer_free(&m);
1102
1103
	debug2("%s: received challenge: %s", __func__, challenge);
1104
1105
	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
1106
1107
	xasprintf(*prompts, "%s%s", challenge, "Virtual Token challenge: ");
1108
	xfree(challenge);
1109
1110
	return (0);
1111
}
1112
1113
int 
1114
mm_vtoken_respond(void *ctx, u_int numresponses, char **responses)
1115
{
1116
	Buffer m;
1117
	int authok, temp=atoi(responses[0]);
1118
        Authctxt *authctxt = ctx;
1119
1120
	debug3("%s entering", __func__);
1121
	if (numresponses != 1)
1122
		return (-1);
1123
1124
	buffer_init(&m);
1125
	buffer_put_cstring(&m, responses[0]);
1126
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_VTOKENRESPOND, &m);
1127
1128
	mm_request_receive_expect(pmonitor->m_recvfd,
1129
	    MONITOR_ANS_VTOKENRESPOND, &m);
1130
1131
	authok = buffer_get_int(&m);
1132
	buffer_free(&m);
1133
			authctxt->postponed = 0;
1134
1135
        if (authctxt->valid &&
1136
                numresponses == 1 &&
1137
                mm_check_user_response(temp)) {
1138
                        return 0;
1139
	}
1140
	return -1;
1141
}
1142
#endif /* USE_VTOKEN*/
1143
1144
1012
void
1145
void
1013
mm_ssh1_session_id(u_char session_id[16])
1146
mm_ssh1_session_id(u_char session_id[16])
1014
{
1147
{
1015
	Buffer m;
1148
	Buffer m;
1016
	int i;
1149
	int i;
(-)openssh-4.7p1/monitor_wrap.h (+4 lines)
Lines 99-108 Link Here
99
99
100
/* skey */
100
/* skey */
101
int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
101
int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
102
int mm_skey_respond(void *, u_int, char **);
102
int mm_skey_respond(void *, u_int, char **);
103
103
104
/* virtual token */
105
int mm_vtoken_query(void *, char **, char **, u_int *, char ***, u_int **);
106
int mm_vtoken_respond(void *, u_int, char **);
107
104
/* zlib allocation hooks */
108
/* zlib allocation hooks */
105
109
106
void *mm_zalloc(struct mm_master *, u_int, u_int);
110
void *mm_zalloc(struct mm_master *, u_int, u_int);
107
void mm_zfree(struct mm_master *, void *);
111
void mm_zfree(struct mm_master *, void *);
108
void mm_init_compression(struct mm_master *);
112
void mm_init_compression(struct mm_master *);
(-)openssh-4.7p1/servconf.c (-1 / +18 lines)
Lines 120-129 Link Here
120
	options->authorized_keys_file2 = NULL;
120
	options->authorized_keys_file2 = NULL;
121
	options->num_accept_env = 0;
121
	options->num_accept_env = 0;
122
	options->permit_tun = -1;
122
	options->permit_tun = -1;
123
	options->num_permitted_opens = -1;
123
	options->num_permitted_opens = -1;
124
	options->adm_forced_command = NULL;
124
	options->adm_forced_command = NULL;
125
	options->vtoken_authentication = -1;
126
	options->max_vtoken_users = 0;
125
}
127
}
126
128
127
void
129
void
128
fill_default_server_options(ServerOptions *options)
130
fill_default_server_options(ServerOptions *options)
129
{
131
{
Lines 261-270 Link Here
261
		error("Compression disabled");
263
		error("Compression disabled");
262
		options->compression = 0;
264
		options->compression = 0;
263
	}
265
	}
264
#endif
266
#endif
265
267
268
	if (options->vtoken_authentication == -1)
269
		options->vtoken_authentication = 1;
270
266
}
271
}
267
272
268
/* Keyword tokens. */
273
/* Keyword tokens. */
269
typedef enum {
274
typedef enum {
270
	sBadOption,		/* == unknown option */
275
	sBadOption,		/* == unknown option */
Lines 290-301 Link Here
290
	sBanner, sUseDNS, sHostbasedAuthentication,
295
	sBanner, sUseDNS, sHostbasedAuthentication,
291
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
296
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
292
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
297
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
293
	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
298
	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
294
	sMatch, sPermitOpen, sForceCommand,
299
	sMatch, sPermitOpen, sForceCommand,
295
	sUsePrivilegeSeparation,
300
        sUsePrivilegeSeparation, sFreetkUsers,
296
	sDeprecated, sUnsupported
301
	sDeprecated, sUnsupported
302
297
} ServerOpCodes;
303
} ServerOpCodes;
298
304
299
#define SSHCFG_GLOBAL	0x01	/* allowed in main section of sshd_config */
305
#define SSHCFG_GLOBAL	0x01	/* allowed in main section of sshd_config */
300
#define SSHCFG_MATCH	0x02	/* allowed inside a Match section */
306
#define SSHCFG_MATCH	0x02	/* allowed inside a Match section */
301
#define SSHCFG_ALL	(SSHCFG_GLOBAL|SSHCFG_MATCH)
307
#define SSHCFG_ALL	(SSHCFG_GLOBAL|SSHCFG_MATCH)
Lines 401-410 Link Here
401
	{ "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
407
	{ "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
402
	{ "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
408
	{ "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
403
 	{ "match", sMatch, SSHCFG_ALL },
409
 	{ "match", sMatch, SSHCFG_ALL },
404
	{ "permitopen", sPermitOpen, SSHCFG_ALL },
410
	{ "permitopen", sPermitOpen, SSHCFG_ALL },
405
	{ "forcecommand", sForceCommand, SSHCFG_ALL },
411
	{ "forcecommand", sForceCommand, SSHCFG_ALL },
412
	{ "vtokenusers", sFreetkUsers, SSHCFG_GLOBAL },
406
	{ NULL, sBadOption, 0 }
413
	{ NULL, sBadOption, 0 }
407
};
414
};
408
415
409
/*
416
/*
410
 * Returns the number of the token pointed to by cp or sBadOption.
417
 * Returns the number of the token pointed to by cp or sBadOption.
Lines 1265-1274 Link Here
1265
		    filename, linenum, arg);
1272
		    filename, linenum, arg);
1266
		while (arg)
1273
		while (arg)
1267
		    arg = strdelim(&cp);
1274
		    arg = strdelim(&cp);
1268
		break;
1275
		break;
1269
1276
1277
	case sFreetkUsers:
1278
		while ((arg = strdelim(&cp)) && *arg != '\0') {
1279
			if (options->max_vtoken_users >= MAX_VTOKEN_USERS)
1280
				fatal("%s line %d: too many vtoken users.",
1281
					filename, linenum);
1282
			options->vtoken_users[options->max_vtoken_users++] =
1283
				xstrdup(arg);
1284
		}
1285
		break;
1286
1270
	default:
1287
	default:
1271
		fatal("%s line %d: Missing handler for opcode %s (%d)",
1288
		fatal("%s line %d: Missing handler for opcode %s (%d)",
1272
		    filename, linenum, arg, opcode);
1289
		    filename, linenum, arg, opcode);
1273
	}
1290
	}
1274
	if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1291
	if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
(-)openssh-4.7p1/servconf.h (+5 lines)
Lines 24-33 Link Here
24
#define MAX_DENY_GROUPS		256	/* Max # groups on deny list. */
24
#define MAX_DENY_GROUPS		256	/* Max # groups on deny list. */
25
#define MAX_SUBSYSTEMS		256	/* Max # subsystems. */
25
#define MAX_SUBSYSTEMS		256	/* Max # subsystems. */
26
#define MAX_HOSTKEYS		256	/* Max # hostkeys. */
26
#define MAX_HOSTKEYS		256	/* Max # hostkeys. */
27
#define MAX_ACCEPT_ENV		256	/* Max # of env vars. */
27
#define MAX_ACCEPT_ENV		256	/* Max # of env vars. */
28
#define MAX_MATCH_GROUPS	256	/* Max # of groups for Match. */
28
#define MAX_MATCH_GROUPS	256	/* Max # of groups for Match. */
29
#define MAX_VTOKEN_USERS	256     /* Max # of free token users. */
29
30
30
/* permit_root_login */
31
/* permit_root_login */
31
#define	PERMIT_NOT_SET		-1
32
#define	PERMIT_NOT_SET		-1
32
#define	PERMIT_NO		0
33
#define	PERMIT_NO		0
33
#define	PERMIT_FORCED_ONLY	1
34
#define	PERMIT_FORCED_ONLY	1
Lines 139-148 Link Here
139
	int	use_pam;		/* Enable auth via PAM */
140
	int	use_pam;		/* Enable auth via PAM */
140
141
141
	int	permit_tun;
142
	int	permit_tun;
142
143
143
	int	num_permitted_opens;
144
	int	num_permitted_opens;
145
146
	int     vtoken_authentication;     /* Permit out-of-band challenge if true */
147
	int     max_vtoken_users;
148
	char    *vtoken_users[MAX_VTOKEN_USERS];
144
}       ServerOptions;
149
}       ServerOptions;
145
150
146
void	 initialize_server_options(ServerOptions *);
151
void	 initialize_server_options(ServerOptions *);
147
void	 fill_default_server_options(ServerOptions *);
152
void	 fill_default_server_options(ServerOptions *);
148
int	 process_server_config_line(ServerOptions *, char *, const char *, int,
153
int	 process_server_config_line(ServerOptions *, char *, const char *, int,
(-)openssh-4.7p1/sshd_config.5 (+10 lines)
Lines 170-179 Link Here
170
All authentication styles from
170
All authentication styles from
171
.Xr login.conf 5
171
.Xr login.conf 5
172
are supported.
172
are supported.
173
The default is
173
The default is
174
.Dq yes .
174
.Dq yes .
175
.It Cm VtokenUsers
176
Specifies the two secrets used to calculate a user's virtual token challenge
177
(VToken). The server generates a VToken challenge and waits for the user's
178
response. The user is authenticated if he/she can respond with the same value.
179
180
Use the format:
181
182
VtokenUsers  username:secret:PIN
183
184
ChallengeResponseAuthentication must be set for ChallengeUsers to work.
175
.It Cm Ciphers
185
.It Cm Ciphers
176
Specifies the ciphers allowed for protocol version 2.
186
Specifies the ciphers allowed for protocol version 2.
177
Multiple ciphers must be comma-separated.
187
Multiple ciphers must be comma-separated.
178
The supported ciphers are
188
The supported ciphers are
179
.Dq 3des-cbc ,
189
.Dq 3des-cbc ,
(-)openssh-4.7p1/README.vtoken (+37 lines)
Line 0 Link Here
1
How to authenticate using the Virtual Token (VToken) Challenge
2
3
Overview:
4
5
The Virtual Token (VToken) patch adds a kbdint device that provides a new challenge-based authentication mechanism. The server calculates a challenge from two secrets and a counter. You authenticate by proving that you know the secrets by correctly answering the challenge. This creates a software-based token, similar in function to commercial ones, that can be run from your workstation or better yet, ubiquitous devices such as PDAs, cell phones, calculators, and even pen and paper. 
6
7
VToken has the advantage of not only using cheap, generic devices but also not being network-aware. Commercial tokens can only be used on networks configured with a significant amount of dedicated infrastructure; they're network-based. VToken can be from on any machine running OpenSSH and a properly configured sshd_config file; it's a host-based system. 
8
9
The current challenge is a place-holder for a more rigorous one. It uses the simple equation: Challenge=Secret*Counter Mod(PIN). The secret is designed to be embedded in the virtual token, while you must keep the PIN secret; the counter protects against replay attacks. Taking the modulus of the product maps the answer into a number set (or something like that) that . Ultimately, the calculation should probably be done by taking the hash of the combined terms (anyone who captures the current challenge will be able to calculate the secrets using brute force).
10
11
vtoken.c is an example virtual token app. It prompts you for your PIN and calculates the challenge response from the secret, which is embedded in it's source.
12
13
VToken in it's present form should be used in conjunction with the "Multiauth" patch (https://bugzilla.mindrot.org/show_bug.cgi?id=1435), which allows you to use multiple authentication methods tolog into a machine. You'll want to use Pubkey together with VToken.
14
15
In the future, VToken will by itself will provide two-factor authentication. The secret will be embedded in the app and effectively be embedded in your PDA, cell phone, etc. You'll keep your PIN separate, of course, and use the two just like on commercial tokens.
16
17
Configuration:
18
19
The user's secrets are stored in sshd_config using the format:
20
21
VTokenUsers username:secret:PIN
22
23
For instance, 
24
25
VTokenUsers paul:1234:4321
26
27
For the time-being the formula is challenge = secret * counter MOD(PIN)
28
Eventually, the formula will probably be challenge = HASH(secret|counter|PIN).
29
30
31
Compilation:
32
33
Install and compile the VToken patch:
34
35
authconf
36
./configure --with-vtoken
37
make install
(-)openssh-4.7p1/vtoken.c (+84 lines)
Line 0 Link Here
1
#include <ctype.h>
2
#include <dirent.h>
3
#include <errno.h>
4
#include <fcntl.h>
5
#include <pwd.h>
6
#include <signal.h>
7
#include <stdarg.h>
8
#include <stdio.h>
9
#include <stdlib.h>
10
#include <string.h>
11
#include <time.h>
12
#include <unistd.h>
13
14
15
#define PIN_LEN 4
16
17
int getpin(void)
18
{
19
	char line[PIN_LEN+1];
20
	int c, n=0, max=PIN_LEN+1;
21
22
	system("stty -echo");
23
	while((c = getchar()) != EOF) {
24
		if(c == '\n')
25
			break;
26
		if(n < max)
27
			line[n++] = c;
28
	}
29
	system("stty echo");
30
	printf("\n");
31
32
	if(c == EOF && n == 0)
33
		return(-1);
34
35
	line[n] = '\0';
36
37
	return atoi(line);
38
}
39
40
get_time(void)
41
{
42
        int secs;
43
        time_t now;
44
        struct tm *its;
45
46
        /* construct term from hours, minutes and seconds */
47
        now = time(NULL);
48
        its = localtime(&now);
49
        secs = its->tm_hour*60*60 + its->tm_min*60 + its->tm_sec;
50
        secs = its->tm_min*60 + its->tm_sec;
51
52
        return(secs);
53
}
54
55
int
56
calculate_challenge(int s1, int s2, int count)
57
{
58
	int challenge;
59
60
        /* !!! proof-of-concept !!! */
61
        /* advantage: you can calculate the secret with paper and pencil
62
                or simple calculator
63
           advanatage: you can build a simple cell phone or pda app to
64
                perform this function
65
           disadvantage: the unknowns can be brute-forced if the
66
                challenge is intercepted */
67
68
	challenge = (count * s1) % s2;
69
70
	return(challenge);
71
}
72
73
int
74
main(int argc, char **argv)
75
{
76
	int pin,count,secret=3361;
77
78
	printf("Enter PIN: ");
79
	pin = getpin();
80
81
	count = get_time();
82
	printf("challenge: %d\n",calculate_challenge(secret,pin,count) );
83
sleep(10);
84
}

Return to bug 1439