2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2024
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "lib/param/param.h"
23 #include "../source4/lib/tls/tls.h"
25 void ndr_print_ads_tlswrap_struct(struct ndr_print
*ndr
, const char *name
, const struct ads_tlswrap
*r
)
27 ndr_print_struct(ndr
, name
, "tlswrap");
29 ndr_print_ptr(ndr
, "mem_ctx", r
->mem_ctx
);
30 ndr_print_timeval(ndr
, "endtime", &r
->endtime
);
32 ndr_print_ptr(ndr
, "sbiod", r
->sbiod
);
33 ndr_print_ptr(ndr
, "tls_params", r
->tls_params
);
34 ndr_print_ptr(ndr
, "tls_sync", r
->tls_sync
);
41 static int ads_tlswrap_setup(Sockbuf_IO_Desc
*sbiod
, void *arg
)
43 struct ads_tlswrap
*wrap
= (struct ads_tlswrap
*)arg
;
47 sbiod
->sbiod_pvt
= wrap
;
52 static int ads_tlswrap_remove(Sockbuf_IO_Desc
*sbiod
)
54 struct ads_tlswrap
*wrap
=
55 (struct ads_tlswrap
*)sbiod
->sbiod_pvt
;
62 static ssize_t
ads_tlswrap_send_function(gnutls_transport_ptr_t ptr
,
63 const uint8_t *buf
, size_t size
)
65 struct ads_tlswrap
*wrap
= (struct ads_tlswrap
*)ptr
;
67 if (wrap
->endtime
.tv_sec
!= 0) {
68 if (timeval_expired(&wrap
->endtime
)) {
74 return LBER_SBIOD_WRITE_NEXT(wrap
->sbiod
, discard_const(buf
), size
);
77 static ssize_t
ads_tlswrap_recv_function(gnutls_transport_ptr_t ptr
,
78 uint8_t *buf
, size_t size
)
80 struct ads_tlswrap
*wrap
= (struct ads_tlswrap
*)ptr
;
82 if (wrap
->endtime
.tv_sec
!= 0) {
83 if (timeval_expired(&wrap
->endtime
)) {
89 return LBER_SBIOD_READ_NEXT(wrap
->sbiod
, buf
, size
);
92 static ber_slen_t
ads_tlswrap_read(Sockbuf_IO_Desc
*sbiod
,
93 void *buf
, ber_len_t len
)
95 struct ads_tlswrap
*wrap
=
96 (struct ads_tlswrap
*)sbiod
->sbiod_pvt
;
98 return tstream_tls_sync_read(wrap
->tls_sync
, buf
, len
);
101 static ber_slen_t
ads_tlswrap_write(Sockbuf_IO_Desc
*sbiod
,
102 void *buf
, ber_len_t len
)
104 struct ads_tlswrap
*wrap
=
105 (struct ads_tlswrap
*)sbiod
->sbiod_pvt
;
107 return tstream_tls_sync_write(wrap
->tls_sync
, buf
, len
);
110 static int ads_tlswrap_ctrl(Sockbuf_IO_Desc
*sbiod
, int opt
, void *arg
)
112 struct ads_tlswrap
*wrap
=
113 (struct ads_tlswrap
*)sbiod
->sbiod_pvt
;
117 case LBER_SB_OPT_DATA_READY
:
118 if (tstream_tls_sync_pending(wrap
->tls_sync
) > 0) {
122 ret
= LBER_SBIOD_CTRL_NEXT(sbiod
, opt
, arg
);
125 ret
= LBER_SBIOD_CTRL_NEXT(sbiod
, opt
, arg
);
132 static int ads_tlswrap_close(Sockbuf_IO_Desc
*sbiod
)
134 struct ads_tlswrap
*wrap
=
135 (struct ads_tlswrap
*)sbiod
->sbiod_pvt
;
137 TALLOC_FREE(wrap
->tls_sync
);
138 TALLOC_FREE(wrap
->tls_params
);
143 static const Sockbuf_IO ads_tlswrap_sockbuf_io
= {
144 ads_tlswrap_setup
, /* sbi_setup */
145 ads_tlswrap_remove
, /* sbi_remove */
146 ads_tlswrap_ctrl
, /* sbi_ctrl */
147 ads_tlswrap_read
, /* sbi_read */
148 ads_tlswrap_write
, /* sbi_write */
149 ads_tlswrap_close
/* sbi_close */
152 ADS_STATUS
ads_setup_tls_wrapping(struct ads_tlswrap
*wrap
,
154 const char *server_name
)
156 TALLOC_CTX
*frame
= talloc_stackframe();
157 Sockbuf_IO
*io
= discard_const_p(Sockbuf_IO
, &ads_tlswrap_sockbuf_io
);
159 struct loadparm_context
*lp_ctx
= NULL
;
165 rc
= ldap_get_option(ld
, LDAP_OPT_SOCKBUF
, &sb
);
166 status
= ADS_ERROR_LDAP(rc
);
167 if (!ADS_ERR_OK(status
)) {
172 lp_ctx
= loadparm_init_s3(frame
, loadparm_s3_helpers());
173 if (lp_ctx
== NULL
) {
175 return ADS_ERROR(LDAP_NO_MEMORY
);
178 ntstatus
= tstream_tls_params_client_lpcfg(wrap
->mem_ctx
,
182 if (!NT_STATUS_IS_OK(ntstatus
)) {
184 return ADS_ERROR_NT(ntstatus
);
187 /* setup the real wrapping callbacks */
188 rc
= ber_sockbuf_add_io(sb
, io
, LBER_SBIOD_LEVEL_TRANSPORT
, wrap
);
189 status
= ADS_ERROR_LDAP(rc
);
190 if (!ADS_ERR_OK(status
)) {
195 to
= lpcfg_ldap_connection_timeout(lp_ctx
);
196 wrap
->endtime
= timeval_current_ofs(to
, 0);
197 ntstatus
= tstream_tls_sync_setup(wrap
->tls_params
,
199 ads_tlswrap_send_function
,
200 ads_tlswrap_recv_function
,
203 wrap
->endtime
= timeval_zero();
204 if (!NT_STATUS_IS_OK(ntstatus
)) {
205 ber_sockbuf_remove_io(sb
, io
, LBER_SBIOD_LEVEL_TRANSPORT
);
207 return ADS_ERROR_NT(ntstatus
);
214 const DATA_BLOB
*ads_tls_channel_bindings(struct ads_tlswrap
*wrap
)
216 if (wrap
->tls_sync
== NULL
) {
220 return tstream_tls_sync_channel_bindings(wrap
->tls_sync
);
223 ADS_STATUS
ads_setup_tls_wrapping(struct ads_tlswrap
*wrap
,
225 const char *server_name
)
227 return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
229 const DATA_BLOB
*ads_tls_channel_bindings(struct ads_tlswrap
*wrap
)
233 #endif /* HAVE_ADS */