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