1 /*
2  * h_auth.c
3  * (C)1998-2011 by Marc Huber <Marc.Huber@web.de>
4  *
5  * $Id: h_auth.c,v 1.14 2015/03/14 06:11:25 marc Exp marc $
6  *
7  */
8 
9 
10 #include "headers.h"
11 #ifdef WITH_SSL
12 #include "misc/ssl_init.h"
13 
14 static const char rcsid[] __attribute__ ((used)) = "$Id: h_auth.c,v 1.14 2015/03/14 06:11:25 marc Exp marc $";
15 
do_accept_c(struct context * ctx,int cur)16 void do_accept_c(struct context *ctx, int cur)
17 {
18     int r;
19 
20     DebugIn(DEBUG_NET);
21 
22     io_sched_renew_proc(ctx->io, ctx, (void *) cleanup);
23 
24     io_clr_i(ctx->io, ctx->cfn);
25     io_clr_o(ctx->io, ctx->cfn);
26 
27     switch (SSL_accept(ctx->ssl_c)) {
28     default:			/* not completed */
29 	r = 0;
30 	io_set_cb_i(ctx->io, ctx->cfn, (void *) do_accept_c);
31 	io_set_cb_o(ctx->io, ctx->cfn, (void *) do_accept_c);
32 
33 	if (SSL_want_read(ctx->ssl_c))
34 	    io_set_i(ctx->io, cur), r++;
35 	if (SSL_want_write(ctx->ssl_c))
36 	    io_set_o(ctx->io, cur), r++;
37 
38 	if (!r) {
39 	    logmsg("SSL_accept(%s:%d): %s", __FILE__, __LINE__, ERR_error_string(ERR_get_error(), NULL));
40 	    cleanup(ctx, cur);
41 	}
42 	break;
43     case 0:			/* failure, controlled shut down */
44 	cleanup(ctx, cur);
45 	break;
46     case 1:			/* completed */
47 	if (ctx->use_tls_c)
48 	    print_banner(ctx);
49 	else {
50 	    io_set_cb_i(ctx->io, ctx->cfn, (void *) readcmd);
51 	    io_set_cb_o(ctx->io, ctx->cfn, (void *) control2socket);
52 	    io_set_i(ctx->io, ctx->cfn);
53 	}
54 	break;
55     }
56     DebugOut(DEBUG_NET);
57 }
58 
do_accept_d(struct context * ctx,int cur)59 static void do_accept_d(struct context *ctx, int cur)
60 {
61     int r;
62     DebugIn(DEBUG_NET);
63 
64     io_sched_renew_proc(ctx->io, ctx, (void *) cleanup);
65 
66     io_clr_i(ctx->io, cur);
67     io_clr_o(ctx->io, cur);
68 
69     switch (SSL_accept(ctx->ssl_d)) {
70     default:			/* not completed */
71 	Debug((DEBUG_NET, "SSL_get_error: %s\n", ERR_error_string(ERR_get_error(), NULL)));
72 	r = 0;
73 
74 	io_set_cb_i(ctx->io, cur, (void *) do_accept_d);
75 	io_set_cb_o(ctx->io, cur, (void *) do_accept_d);
76 
77 	if (SSL_want_read(ctx->ssl_d)) {
78 	    io_set_i(ctx->io, cur);
79 	    r++;
80 	}
81 	if (SSL_want_write(ctx->ssl_d)) {
82 	    io_set_o(ctx->io, cur);
83 	    r++;
84 	}
85 
86 	if (!r) {
87 	    logmsg("SSL_accept(%s:%d): %s", __FILE__, __LINE__, ERR_error_string(ERR_get_error(), NULL));
88 	    cleanup(ctx, cur);
89 	}
90 	Debug((DEBUG_NET, "SSL handshake in progress.\n"));
91 	break;
92     case 0:			/* failure, controlled shut down */
93 	Debug((DEBUG_NET, "SSL handshake failed.\n"));
94 	cleanup(ctx, cur);
95 	break;
96     case 1:			/* completed */
97 	Debug((DEBUG_NET, "SSL connection established.\n"));
98 	do_connect_d(ctx, cur);
99 	break;
100     }
101 
102     DebugOut(DEBUG_NET);
103 }
104 
sslify_c(struct context * ctx,int cur)105 void sslify_c(struct context *ctx, int cur)
106 {
107     Debug((DEBUG_NET, "%s.\n", __func__));
108     if (!ctx->ssl_c) {
109 	if (ctx->cbufo && ctx->cbufo->length - ctx->cbufo->offset)
110 	    control2socket(ctx, cur);
111 	if (ctx->cbufo && ctx->cbufo->length - ctx->cbufo->offset)
112 	    io_set_cb_o(ctx->io, cur, (void *) sslify_c);
113 	else {
114 	    io_set_cb_e(ctx->io, cur, (void *) cleanup_control_ssl_error);
115 	    io_set_cb_h(ctx->io, cur, (void *) cleanup_control_ssl_error);
116 	    if (ssl_auth)
117 		ssl_set_verify(ssl_ctx, ctx);
118 	    ctx->ssl_c = SSL_new(ssl_ctx);
119 	    SSL_set_fd(ctx->ssl_c, ctx->cfn);
120 	    do_accept_c(ctx, cur);
121 	}
122     }
123 }
124 
sslify_d(struct context * ctx,int cur)125 void sslify_d(struct context *ctx, int cur)
126 {
127     Debug((DEBUG_NET, "%s.\n", __func__));
128     if (!ctx->ssl_d) {
129 	io_set_cb_e(ctx->io, cur, (void *) cleanup_data_ssl_error);
130 	io_set_cb_h(ctx->io, cur, (void *) cleanup_data_ssl_error);
131 	if (ssl_auth)
132 	    ssl_set_verify(ssl_ctx, ctx);
133 	ctx->ssl_d = SSL_new(ssl_ctx);
134 #if 0
135 	/* doesn't work as expected */
136 	if (ctx->ssl_c)
137 	    SSL_copy_session_id(ctx->ssl_d, ctx->ssl_c);
138 #endif
139 	SSL_set_fd(ctx->ssl_d, ctx->dfn);
140 	do_accept_d(ctx, cur);
141     }
142 }
143 
h_auth(struct context * ctx,char * arg)144 void h_auth(struct context *ctx, char *arg)
145 {
146     DebugIn(DEBUG_COMMAND);
147     if (!ssl_ctx)
148 	reply(ctx, MSG_500_AUTH_not_supported);
149     else if (ctx->ssl_c)
150 	reply(ctx, MSG_501_AUTH_SSL_already_active);
151     else if (!strcasecmp(arg, "ssl")) {
152 	ctx->protected_buffer_size = 0,	/* PBSZ 0 */
153 	    ctx->use_tls_d = 1;	/* PROT P */
154 	reply(ctx, ssl_old_draft ? MSG_334_AUTH_SSL_OK : MSG_234_AUTH_SSL_OK);
155 	sslify_c(ctx, ctx->cfn);
156     } else if (!strcasecmp(arg, "tls-p")) {
157 	ctx->use_tls_d = 1;	/* PROT P */
158 	reply(ctx, ssl_old_draft ? MSG_334_AUTH_SSL_OK : MSG_234_AUTH_SSL_OK);
159 	sslify_c(ctx, ctx->cfn);
160     } else if (!strcasecmp(arg, "tls") || !strcasecmp(arg, "tls-c")) {
161 	ctx->use_tls_d = 0;	/* PROT C */
162 	reply(ctx, ssl_old_draft ? MSG_334_AUTH_SSL_OK : MSG_234_AUTH_SSL_OK);
163 	sslify_c(ctx, ctx->cfn);
164     } else
165 	reply(ctx, MSG_504_AUTH_type_not_supported);
166 
167     DebugOut(DEBUG_COMMAND);
168 }
169 #endif
170