blob: 1e57b25871c5c7bdefef680421e3d7a210bbba2f [file] [log] [blame]
roman3f9b65c2023-06-05 14:26:58 +02001/**
2 * @file config_new.c
3 * @author Roman Janota <janota@cesnet.cz>
4 * @brief libnetconf2 server new configuration creation functions
5 *
6 * @copyright
7 * Copyright (c) 2023 CESNET, z.s.p.o.
8 *
9 * This source code is licensed under BSD 3-Clause License (the "License").
10 * You may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * https://opensource.org/licenses/BSD-3-Clause
14 */
15
16#define _GNU_SOURCE
17
roman2eab4742023-06-06 10:00:26 +020018#include <libyang/libyang.h>
romand30af552023-06-16 15:18:27 +020019#include <stdarg.h>
roman3f9b65c2023-06-05 14:26:58 +020020#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
roman2eab4742023-06-06 10:00:26 +020024#ifdef NC_ENABLED_SSH_TLS
roman3f9b65c2023-06-05 14:26:58 +020025#include <libssh/libssh.h>
roman3f9b65c2023-06-05 14:26:58 +020026#include <openssl/err.h>
27#include <openssl/evp.h>
28#include <openssl/pem.h>
roman2eab4742023-06-06 10:00:26 +020029#endif /* NC_ENABLED_SSH_TLS */
roman3f9b65c2023-06-05 14:26:58 +020030
31#include "compat.h"
32#include "config_new.h"
33#include "log_p.h"
34#include "session.h"
35#include "session_p.h"
36
37int
38nc_config_new_check_add_operation(const struct ly_ctx *ctx, struct lyd_node *top)
39{
40 if (lyd_find_meta(top->meta, NULL, "yang:operation")) {
41 /* it already has operation attribute */
42 return 0;
43 }
44
45 /* give the top level container create operation */
46 if (lyd_new_meta(ctx, top, NULL, "yang:operation", "create", 0, NULL)) {
47 return 1;
48 }
49
50 return 0;
51}
52
roman2eab4742023-06-06 10:00:26 +020053#ifdef NC_ENABLED_SSH_TLS
54
roman3f9b65c2023-06-05 14:26:58 +020055const char *
56nc_config_new_privkey_format_to_identityref(NC_PRIVKEY_FORMAT format)
57{
58 switch (format) {
59 case NC_PRIVKEY_FORMAT_RSA:
60 return "ietf-crypto-types:rsa-private-key-format";
61 case NC_PRIVKEY_FORMAT_EC:
62 return "ietf-crypto-types:ec-private-key-format";
63 case NC_PRIVKEY_FORMAT_X509:
64 return "libnetconf2-netconf-server:subject-private-key-info-format";
65 case NC_PRIVKEY_FORMAT_OPENSSH:
66 return "libnetconf2-netconf-server:openssh-private-key-format";
67 default:
68 ERR(NULL, "Private key type not supported.");
69 return NULL;
70 }
71}
72
73int
74nc_server_config_new_read_certificate(const char *cert_path, char **cert)
75{
76 int ret = 0, cert_len;
77 X509 *x509 = NULL;
78 FILE *f = NULL;
79 BIO *bio = NULL;
80 char *c = NULL;
81
82 *cert = NULL;
83
84 f = fopen(cert_path, "r");
85 if (!f) {
86 ERR(NULL, "Unable to open certificate file \"%s\".", cert_path);
87 ret = 1;
88 goto cleanup;
89 }
90
91 /* load the cert into memory */
92 x509 = PEM_read_X509(f, NULL, NULL, NULL);
93 if (!x509) {
94 ret = -1;
95 goto cleanup;
96 }
97
98 bio = BIO_new(BIO_s_mem());
99 if (!bio) {
100 ret = -1;
101 goto cleanup;
102 }
103
104 ret = PEM_write_bio_X509(bio, x509);
105 if (!ret) {
106 ret = -1;
107 goto cleanup;
108 }
109
110 cert_len = BIO_pending(bio);
111 if (cert_len <= 0) {
112 ret = -1;
113 goto cleanup;
114 }
115
116 c = malloc(cert_len + 1);
117 if (!c) {
118 ERRMEM;
119 ret = 1;
120 goto cleanup;
121 }
122
123 /* read the cert from bio */
124 ret = BIO_read(bio, c, cert_len);
125 if (ret <= 0) {
126 ret = -1;
127 goto cleanup;
128 }
129 c[cert_len] = '\0';
130
131 /* strip the cert of the header and footer */
132 *cert = strdup(c + strlen(NC_PEM_CERTIFICATE_HEADER));
133 if (!*cert) {
134 ERRMEM;
135 ret = 1;
136 goto cleanup;
137 }
138
139 (*cert)[strlen(*cert) - strlen(NC_PEM_CERTIFICATE_FOOTER)] = '\0';
140
141 ret = 0;
142
143cleanup:
144 if (ret == -1) {
145 ERR(NULL, "Error getting certificate from file \"%s\" (OpenSSL Error): \"%s\".", cert_path, ERR_reason_error_string(ERR_get_error()));
146 ret = 1;
147 }
148 if (f) {
149 fclose(f);
150 }
151
152 BIO_free(bio);
153 X509_free(x509);
154 free(c);
155 return ret;
156}
157
158static int
159nc_server_config_new_read_ssh2_pubkey(FILE *f, char **pubkey)
160{
161 char *buffer = NULL;
162 size_t size = 0, pubkey_len = 0;
163 void *tmp;
164 ssize_t read;
165 int ret = 0;
166
167 while ((read = getline(&buffer, &size, f)) > 0) {
168 if (!strncmp(buffer, "----", 4)) {
169 continue;
170 }
171
172 if (!strncmp(buffer, "Comment:", 8)) {
173 continue;
174 }
175
176 if (buffer[read - 1] == '\n') {
177 read--;
178 }
179
180 tmp = realloc(*pubkey, pubkey_len + read + 1);
181 if (!tmp) {
182 ERRMEM;
183 ret = 1;
184 goto cleanup;
185 }
186
187 *pubkey = tmp;
188 memcpy(*pubkey + pubkey_len, buffer, read);
189 pubkey_len += read;
190 }
191
192 if (!pubkey_len) {
193 ERR(NULL, "Unexpected public key format.");
194 ret = 1;
195 goto cleanup;
196 }
197
198 (*pubkey)[pubkey_len] = '\0';
199
200cleanup:
201 free(buffer);
202 return ret;
203}
204
205static int
206nc_server_config_new_read_pubkey_openssl(FILE *f, char **pubkey)
207{
208 int ret = 0;
209 EVP_PKEY *pkey = NULL;
210 BIO *bio = NULL;
211 char *key = NULL;
212 int pub_len;
213
214 /* read the pubkey from file */
215 pkey = PEM_read_PUBKEY(f, NULL, NULL, NULL);
216 if (!pkey) {
217 ret = -1;
218 goto cleanup;
219 }
220
221 bio = BIO_new(BIO_s_mem());
222 if (!bio) {
223 ret = -1;
224 goto cleanup;
225 }
226
227 /* write the pubkey into bio */
228 ret = PEM_write_bio_PUBKEY(bio, pkey);
229 if (!ret) {
230 ret = -1;
231 goto cleanup;
232 }
233
234 pub_len = BIO_pending(bio);
235 if (pub_len <= 0) {
236 ret = -1;
237 goto cleanup;
238 }
239
240 /* get pubkey's length */
241 key = malloc(pub_len + 1);
242 if (!key) {
243 ERRMEM;
244 ret = 1;
245 goto cleanup;
246 }
247
248 /* read the public key from bio */
249 ret = BIO_read(bio, key, pub_len);
250 if (ret <= 0) {
251 ret = -1;
252 goto cleanup;
253 }
254 key[pub_len] = '\0';
255
256 /* strip the pubkey of the header and footer */
257 *pubkey = strdup(key + strlen(NC_SUBJECT_PUBKEY_INFO_HEADER));
258 if (!*pubkey) {
259 ERRMEM;
260 ret = 1;
261 goto cleanup;
262 }
263
264 (*pubkey)[strlen(*pubkey) - strlen(NC_SUBJECT_PUBKEY_INFO_FOOTER)] = '\0';
265
266 ret = 0;
267cleanup:
268 if (ret == -1) {
269 ERR(NULL, "Error getting public key from file (OpenSSL Error): \"%s\".", ERR_reason_error_string(ERR_get_error()));
270 ret = 1;
271 }
272
273 BIO_free(bio);
274 EVP_PKEY_free(pkey);
275 free(key);
276
277 return ret;
278}
279
roman3f9b65c2023-06-05 14:26:58 +0200280static int
281nc_server_config_new_read_pubkey_libssh(const char *pubkey_path, char **pubkey)
282{
283 int ret = 0;
284 ssh_key pub_sshkey = NULL;
285
286 ret = ssh_pki_import_pubkey_file(pubkey_path, &pub_sshkey);
287 if (ret) {
288 ERR(NULL, "Importing public key from file \"%s\" failed.", pubkey_path);
289 return ret;
290 }
291
292 ret = ssh_pki_export_pubkey_base64(pub_sshkey, pubkey);
293 if (ret) {
294 ERR(NULL, "Exporting public key to base64 failed.");
295 }
296
297 ssh_key_free(pub_sshkey);
298 return ret;
299}
300
roman3f9b65c2023-06-05 14:26:58 +0200301int
302nc_server_config_new_get_pubkey(const char *pubkey_path, char **pubkey, NC_PUBKEY_FORMAT *pubkey_type)
303{
304 int ret = 0;
305 FILE *f = NULL;
306 char *header = NULL;
307 size_t len = 0;
308
309 NC_CHECK_ARG_RET(NULL, pubkey, pubkey_type, 1);
310
311 *pubkey = NULL;
312
313 f = fopen(pubkey_path, "r");
314 if (!f) {
315 ERR(NULL, "Unable to open file \"%s\".", pubkey_path);
316 ret = 1;
317 goto cleanup;
318 }
319
320 if (getline(&header, &len, f) < 0) {
321 ERR(NULL, "Error reading header from file \"%s\".", pubkey_path);
322 ret = 1;
323 goto cleanup;
324 }
325 rewind(f);
326
327 if (!strncmp(header, NC_SUBJECT_PUBKEY_INFO_HEADER, strlen(NC_SUBJECT_PUBKEY_INFO_HEADER))) {
328 /* it's subject public key info public key */
329 ret = nc_server_config_new_read_pubkey_openssl(f, pubkey);
330 *pubkey_type = NC_PUBKEY_FORMAT_X509;
331 } else if (!strncmp(header, NC_SSH2_PUBKEY_HEADER, strlen(NC_SSH2_PUBKEY_HEADER))) {
332 /* it's ssh2 public key */
333 ret = nc_server_config_new_read_ssh2_pubkey(f, pubkey);
334 *pubkey_type = NC_PUBKEY_FORMAT_SSH2;
roman7fdc84d2023-06-06 13:14:53 +0200335 } else {
roman3f9b65c2023-06-05 14:26:58 +0200336 /* it's probably OpenSSH public key */
337 ret = nc_server_config_new_read_pubkey_libssh(pubkey_path, pubkey);
338 *pubkey_type = NC_PUBKEY_FORMAT_SSH2;
339 }
roman3f9b65c2023-06-05 14:26:58 +0200340
341 if (ret) {
342 ERR(NULL, "Error getting public key from file \"%s\".", pubkey_path);
343 goto cleanup;
344 }
345
346cleanup:
347 if (f) {
348 fclose(f);
349 }
350
351 free(header);
352
353 return ret;
354}
355
356static int
357nc_server_config_new_get_privkey_openssl(FILE *f, char **privkey, EVP_PKEY **priv_pkey)
358{
359 int ret = 0, priv_len;
360 BIO *bio = NULL;
361
362 NC_CHECK_ARG_RET(NULL, privkey, priv_pkey, 1);
363
364 /* read private key from file */
365 *priv_pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL);
366 if (!*priv_pkey) {
367 ret = -1;
368 goto cleanup;
369 }
370
371 bio = BIO_new(BIO_s_mem());
372 if (!bio) {
373 ret = -1;
374 goto cleanup;
375 }
376
377 /* write the private key in to bio */
378 ret = PEM_write_bio_PrivateKey(bio, *priv_pkey, NULL, NULL, 0, NULL, NULL);
379 if (!ret) {
380 ret = -1;
381 goto cleanup;
382 }
383
384 priv_len = BIO_pending(bio);
385 if (priv_len <= 0) {
386 ret = -1;
387 goto cleanup;
388 }
389
390 /* get private key's length */
391 *privkey = malloc(priv_len + 1);
392 if (!*privkey) {
393 ERRMEM;
394 ret = 1;
395 goto cleanup;
396 }
397
398 /* read the private key from bio */
399 ret = BIO_read(bio, *privkey, priv_len);
400 if (ret <= 0) {
401 ret = -1;
402 goto cleanup;
403 }
404 (*privkey)[priv_len] = '\0';
405
406 ret = 0;
407cleanup:
408 if (ret < 0) {
409 ERR(NULL, "Getting private key from file failed (%s).", ERR_reason_error_string(ERR_get_error()));
410 }
411 BIO_free(bio);
412 return ret;
413}
414
415static int
416nc_server_config_new_privkey_to_pubkey_openssl(EVP_PKEY *priv_pkey, char **pubkey)
417{
418 int ret = 0, pub_len;
419 BIO *bio = NULL;
420
421 bio = BIO_new(BIO_s_mem());
422 if (!bio) {
423 ret = -1;
424 goto cleanup;
425 }
426
427 /* write the pubkey into bio */
428 ret = PEM_write_bio_PUBKEY(bio, priv_pkey);
429 if (!ret) {
430 ret = -1;
431 goto cleanup;
432 }
433
434 /* get the length of the pubkey */
435 pub_len = BIO_pending(bio);
436 if (pub_len <= 0) {
437 ret = -1;
438 goto cleanup;
439 }
440
441 *pubkey = malloc(pub_len + 1);
442 if (!*pubkey) {
443 ERRMEM;
444 ret = 1;
445 goto cleanup;
446 }
447
448 /* read the pubkey from the bio */
449 ret = BIO_read(bio, *pubkey, pub_len);
450 if (ret <= 0) {
451 ret = -1;
452 goto cleanup;
453 }
454 (*pubkey)[pub_len] = '\0';
455
456 ret = 0;
457
458cleanup:
459 if (ret < 0) {
460 ERR(NULL, "Converting private to public key failed (%s).", ERR_reason_error_string(ERR_get_error()));
461 }
462 BIO_free(bio);
463 return ret;
464}
465
466static int
467nc_server_config_new_privkey_to_pubkey_libssh(const ssh_key priv_sshkey, char **pubkey)
468{
469 int ret;
470 ssh_key pub_sshkey = NULL;
471
472 ret = ssh_pki_export_privkey_to_pubkey(priv_sshkey, &pub_sshkey);
473 if (ret) {
474 ERR(NULL, "Exporting privkey to pubkey failed.");
475 return ret;
476 }
477
478 ret = ssh_pki_export_pubkey_base64(pub_sshkey, pubkey);
479 if (ret) {
480 ERR(NULL, "Exporting pubkey to base64 failed.");
481 }
482
483 ssh_key_free(pub_sshkey);
484 return ret;
485}
486
487static int
488nc_server_config_new_privkey_to_pubkey(EVP_PKEY *priv_pkey, const ssh_key priv_sshkey, NC_PRIVKEY_FORMAT privkey_type, char **pubkey, NC_PUBKEY_FORMAT *pubkey_type)
489{
490 switch (privkey_type) {
roman3f9b65c2023-06-05 14:26:58 +0200491 case NC_PRIVKEY_FORMAT_RSA:
492 case NC_PRIVKEY_FORMAT_EC:
493 case NC_PRIVKEY_FORMAT_OPENSSH:
494 *pubkey_type = NC_PUBKEY_FORMAT_SSH2;
495 return nc_server_config_new_privkey_to_pubkey_libssh(priv_sshkey, pubkey);
roman3f9b65c2023-06-05 14:26:58 +0200496 case NC_PRIVKEY_FORMAT_X509:
497 *pubkey_type = NC_PUBKEY_FORMAT_X509;
498 return nc_server_config_new_privkey_to_pubkey_openssl(priv_pkey, pubkey);
499 default:
500 break;
501 }
502
503 return 1;
504}
505
roman3f9b65c2023-06-05 14:26:58 +0200506static int
507nc_server_config_new_get_privkey_libssh(const char *privkey_path, char **privkey, ssh_key *priv_sshkey)
508{
509 int ret;
510
511 *priv_sshkey = NULL;
512
513 ret = ssh_pki_import_privkey_file(privkey_path, NULL, NULL, NULL, priv_sshkey);
514 if (ret) {
515 ERR(NULL, "Importing privkey from file \"%s\" failed.", privkey_path);
516 return ret;
517 }
518
519 ret = ssh_pki_export_privkey_base64(*priv_sshkey, NULL, NULL, NULL, privkey);
520 if (ret) {
521 ERR(NULL, "Exporting privkey from file \"%s\" to base64 failed.", privkey_path);
522 }
523
524 return ret;
525}
526
roman3f9b65c2023-06-05 14:26:58 +0200527int
528nc_server_config_new_get_keys(const char *privkey_path, const char *pubkey_path,
529 char **privkey, char **pubkey, NC_PRIVKEY_FORMAT *privkey_type, NC_PUBKEY_FORMAT *pubkey_type)
530{
531 int ret = 0;
532 EVP_PKEY *priv_pkey = NULL;
533 ssh_key priv_sshkey = NULL;
534 FILE *f_privkey = NULL;
535 char *header = NULL;
536 size_t len = 0;
romand30af552023-06-16 15:18:27 +0200537 char *priv = NULL, *pub = NULL;
roman3f9b65c2023-06-05 14:26:58 +0200538
539 NC_CHECK_ARG_RET(NULL, privkey_path, privkey, pubkey, privkey_type, 1);
540
541 *privkey = NULL;
542 *pubkey = NULL;
543
544 /* get private key first */
545 f_privkey = fopen(privkey_path, "r");
546 if (!f_privkey) {
547 ERR(NULL, "Unable to open file \"%s\".", privkey_path);
548 ret = 1;
549 goto cleanup;
550 }
551
552 if (getline(&header, &len, f_privkey) < 0) {
553 ERR(NULL, "Error reading header from file \"%s\".", privkey_path);
554 ret = 1;
555 goto cleanup;
556 }
557 rewind(f_privkey);
558
559 if (!strncmp(header, NC_PKCS8_PRIVKEY_HEADER, strlen(NC_PKCS8_PRIVKEY_HEADER))) {
560 /* it's PKCS8 (X.509) private key */
561 *privkey_type = NC_PRIVKEY_FORMAT_X509;
romand30af552023-06-16 15:18:27 +0200562 ret = nc_server_config_new_get_privkey_openssl(f_privkey, &priv, &priv_pkey);
roman2eab4742023-06-06 10:00:26 +0200563 } else if (!strncmp(header, NC_OPENSSH_PRIVKEY_HEADER, strlen(NC_OPENSSH_PRIVKEY_HEADER))) {
roman3f9b65c2023-06-05 14:26:58 +0200564 /* it's OpenSSH private key */
565 *privkey_type = NC_PRIVKEY_FORMAT_OPENSSH;
romand30af552023-06-16 15:18:27 +0200566 ret = nc_server_config_new_get_privkey_libssh(privkey_path, &priv, &priv_sshkey);
roman3f9b65c2023-06-05 14:26:58 +0200567 } else if (!strncmp(header, NC_PKCS1_RSA_PRIVKEY_HEADER, strlen(NC_PKCS1_RSA_PRIVKEY_HEADER))) {
568 /* it's RSA privkey in PKCS1 format */
569 *privkey_type = NC_PRIVKEY_FORMAT_RSA;
romand30af552023-06-16 15:18:27 +0200570 ret = nc_server_config_new_get_privkey_libssh(privkey_path, &priv, &priv_sshkey);
roman3f9b65c2023-06-05 14:26:58 +0200571 } else if (!strncmp(header, NC_SEC1_EC_PRIVKEY_HEADER, strlen(NC_SEC1_EC_PRIVKEY_HEADER))) {
572 /* it's EC privkey in SEC1 format */
573 *privkey_type = NC_PRIVKEY_FORMAT_EC;
romand30af552023-06-16 15:18:27 +0200574 ret = nc_server_config_new_get_privkey_libssh(privkey_path, &priv, &priv_sshkey);
roman2eab4742023-06-06 10:00:26 +0200575 } else {
roman3f9b65c2023-06-05 14:26:58 +0200576 ERR(NULL, "Private key format not supported.");
577 ret = 1;
578 goto cleanup;
579 }
roman3f9b65c2023-06-05 14:26:58 +0200580 if (ret) {
581 goto cleanup;
582 }
583
584 if (pubkey_path) {
romand30af552023-06-16 15:18:27 +0200585 ret = nc_server_config_new_get_pubkey(pubkey_path, &pub, pubkey_type);
roman3f9b65c2023-06-05 14:26:58 +0200586 } else {
romand30af552023-06-16 15:18:27 +0200587 ret = nc_server_config_new_privkey_to_pubkey(priv_pkey, priv_sshkey, *privkey_type, &pub, pubkey_type);
roman3f9b65c2023-06-05 14:26:58 +0200588 }
roman3f9b65c2023-06-05 14:26:58 +0200589 if (ret) {
590 ERR(NULL, "Getting public key failed.");
591 goto cleanup;
592 }
593
romand30af552023-06-16 15:18:27 +0200594 /* strip pubkey's header and footer only if it's generated from pkcs8 key (using OpenSSL),
595 * otherwise it's already stripped
596 */
597 if (!pubkey_path && (*privkey_type == NC_PRIVKEY_FORMAT_X509)) {
598 *pubkey = strdup(pub + strlen(NC_SUBJECT_PUBKEY_INFO_HEADER));
599 if (!*pubkey) {
600 ERRMEM;
601 ret = 1;
602 goto cleanup;
603 }
604 (*pubkey)[strlen(*pubkey) - strlen(NC_SUBJECT_PUBKEY_INFO_FOOTER)] = '\0';
605 } else {
606 *pubkey = strdup(pub);
607 if (!*pubkey) {
608 ERRMEM;
609 ret = 1;
610 goto cleanup;
611 }
612 }
613
614 /* strip private key's header and footer */
615 if (*privkey_type == NC_PRIVKEY_FORMAT_OPENSSH) {
616 /* only OpenSSH private keys have different header and footer after processing */
617 *privkey = strdup(priv + strlen(NC_OPENSSH_PRIVKEY_HEADER));
618 if (!*privkey) {
619 ERRMEM;
620 ret = 1;
621 goto cleanup;
622 }
623 (*privkey)[strlen(*privkey) - strlen(NC_OPENSSH_PRIVKEY_FOOTER)] = '\0';
624 } else {
625 /* the rest share the same header and footer */
626 *privkey = strdup(priv + strlen(NC_PKCS8_PRIVKEY_HEADER));
627 if (!*privkey) {
628 ERRMEM;
629 ret = 1;
630 goto cleanup;
631 }
632 (*privkey)[strlen(*privkey) - strlen(NC_PKCS8_PRIVKEY_FOOTER)] = '\0';
633 }
634
roman3f9b65c2023-06-05 14:26:58 +0200635cleanup:
636 if (f_privkey) {
637 fclose(f_privkey);
638 }
639
640 free(header);
romand30af552023-06-16 15:18:27 +0200641 free(pub);
642 free(priv);
roman3f9b65c2023-06-05 14:26:58 +0200643
644 ssh_key_free(priv_sshkey);
645 EVP_PKEY_free(priv_pkey);
646
647 return ret;
648}
649
650API int
651nc_server_config_new_address_port(const struct ly_ctx *ctx, const char *endpt_name, NC_TRANSPORT_IMPL transport,
652 const char *address, const char *port, struct lyd_node **config)
653{
654 int ret = 0;
romand30af552023-06-16 15:18:27 +0200655 const char *address_fmt, *port_fmt;
roman3f9b65c2023-06-05 14:26:58 +0200656
657 NC_CHECK_ARG_RET(NULL, address, port, ctx, endpt_name, config, 1);
658
roman3f9b65c2023-06-05 14:26:58 +0200659 if (transport == NC_TI_LIBSSH) {
romand30af552023-06-16 15:18:27 +0200660 /* SSH path */
661 address_fmt = "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/local-address";
662 port_fmt = "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/local-port";
roman2eab4742023-06-06 10:00:26 +0200663 } else if (transport == NC_TI_OPENSSL) {
romand30af552023-06-16 15:18:27 +0200664 /* TLS path */
665 address_fmt = "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/local-address";
666 port_fmt = "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/local-port";
roman2eab4742023-06-06 10:00:26 +0200667 } else {
668 ERR(NULL, "Transport not supported.");
669 ret = 1;
670 goto cleanup;
roman3f9b65c2023-06-05 14:26:58 +0200671 }
roman3f9b65c2023-06-05 14:26:58 +0200672
romand30af552023-06-16 15:18:27 +0200673 ret = nc_config_new_insert(ctx, config, address, address_fmt, endpt_name);
roman3f9b65c2023-06-05 14:26:58 +0200674 if (ret) {
675 goto cleanup;
676 }
677
romand30af552023-06-16 15:18:27 +0200678 ret = nc_config_new_insert(ctx, config, port, port_fmt, endpt_name);
roman3f9b65c2023-06-05 14:26:58 +0200679 if (ret) {
680 goto cleanup;
681 }
romand30af552023-06-16 15:18:27 +0200682
roman3f9b65c2023-06-05 14:26:58 +0200683cleanup:
romand30af552023-06-16 15:18:27 +0200684 return ret;
685}
686
687int
688nc_config_new_insert(const struct ly_ctx *ctx, struct lyd_node **tree, const char *value, const char *path_fmt, ...)
689{
690 int ret = 0;
691 va_list ap;
692 char *path = NULL;
693
694 va_start(ap, path_fmt);
695
696 /* create the path from the format */
697 ret = vasprintf(&path, path_fmt, ap);
698 if (ret == -1) {
699 ERRMEM;
700 path = NULL;
701 goto cleanup;
702 }
703
704 /* create the nodes in the path */
705 ret = lyd_new_path(*tree, ctx, path, value, LYD_NEW_PATH_UPDATE, tree);
706 if (ret) {
707 goto cleanup;
708 }
709
710 /* set out param to top level container */
711 ret = lyd_find_path(*tree, "/ietf-netconf-server:netconf-server", 0, tree);
712 if (ret) {
713 goto cleanup;
714 }
715
716 /* check if top-level container has operation and if not, add it */
717 ret = nc_config_new_check_add_operation(ctx, *tree);
718 if (ret) {
719 goto cleanup;
720 }
721
722 /* add all default nodes */
723 ret = lyd_new_implicit_tree(*tree, LYD_IMPLICIT_NO_STATE, NULL);
724 if (ret) {
725 goto cleanup;
726 }
727
728cleanup:
729 free(path);
730 va_end(ap);
roman3f9b65c2023-06-05 14:26:58 +0200731 return ret;
732}
roman2eab4742023-06-06 10:00:26 +0200733
734#endif /* NC_ENABLED_SSH_TLS */