Add NETCONF CallHome via TLS feature.
[sim/o1-interface.git] / ntsimulator / ntsim-ng / core / nc_config.c
1 /*************************************************************************
2 *
3 * Copyright 2020 highstreet technologies GmbH and others
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
17
18 #define _GNU_SOURCE
19
20 #include "nc_config.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23 #include "utils/http_client.h"
24
25 #include <string.h>
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <assert.h>
29
30 #include <libyang/libyang.h>
31 #include "core/session.h"
32 #include "core/xpath.h"
33 #include "core/framework.h"
34
35 #define GEN_KEY_SCRIPT                              "/home/netconf/.ssh/generate-ssh-keys.sh"
36 #define SERVER_PRIVATE_KEY_PATH                     "/home/netconf/.ssh/melacon.server.key"
37 #define SERVER_PUBLIC_KEY_PATH                      "/home/netconf/.ssh/melacon.server.key.pub.pem"
38 #define CA_CERT_PATH                                "/home/netconf/.ssh/ca.pem"
39
40 static int nc_config_netconf_port = STANDARD_NETCONF_PORT;
41
42 static int load_ssh_keys(sr_session_ctx_t *session);
43 static int load_trusted_certificates(sr_session_ctx_t *session);
44 static int configure_nacm(sr_session_ctx_t *session);
45 static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_connections);
46 static int create_tls_listen_endpoints(struct lyd_node *netconf_node, int tls_connections);
47 static int configure_endpoints_connections(sr_session_ctx_t *session);
48
49 int netconf_configure(void) {
50     int rc = NTS_ERR_OK;
51
52     nc_config_netconf_port = STANDARD_NETCONF_PORT;
53
54     //check if was already ran
55     sr_val_t *val = 0;
56     rc = sr_get_item(session_running, IETF_KEYSTORE_SCHEMA_XPATH, 0, &val);
57     if(rc != SR_ERR_OK) {
58         log_error("sr_get_item failed\n");
59         return NTS_ERR_FAILED;
60     }
61     
62     bool already_done = (val->dflt == false);
63     sr_free_val(val);
64     val = 0;
65     if(already_done) {
66         log_add_verbose(2, "netconf_configure() already ran, skipping...\n");
67         return NTS_ERR_OK;
68     }
69
70     // generate and load private keys
71     log_add_verbose(1, "ietf-keystore startup datastore configuration...");
72     rc = load_ssh_keys(session_running);
73     if(rc != 0) {
74         log_error("could not load SSH keys\n");
75         return NTS_ERR_FAILED;
76     }
77     log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
78
79     // load trusted certificates
80     log_add_verbose(1, "ietf-truststore startup datastore configuration...");
81     rc = load_trusted_certificates(session_running);
82     if(rc != 0) {
83         log_error("could not load trusted certificates\n");
84         return NTS_ERR_FAILED;
85     }
86     log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
87
88     // configuring NACM
89     log_add_verbose(1, "configuring NACM...");
90     rc = configure_nacm(session_running);
91     if(rc != 0) {
92         log_error("could not configure NACM\n");
93         return NTS_ERR_FAILED;
94     }
95     log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
96
97     // configure SSH connections
98     log_add_verbose(1, "Configuring connection endpoints...");
99     rc = configure_endpoints_connections(session_running);
100     if(rc != 0) {
101         log_error("could not configure endpoint connections for NETCONF Server\n");
102         return NTS_ERR_FAILED;
103     }
104     log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
105
106     return NTS_ERR_OK;
107 }
108
109 static int load_ssh_keys(sr_session_ctx_t *session) {
110     assert(session);
111
112     int rc = NTS_ERR_OK;
113     char xpath[500];
114     struct lyd_node *rcl = 0;
115
116     rc = system(GEN_KEY_SCRIPT);
117     if(rc != 0) {
118         log_error("could not generate the SSH keys\n");
119         return NTS_ERR_FAILED;
120     }
121
122     struct lys_module *module;
123     module = (struct lys_module *)ly_ctx_get_module(session_context, IETF_KEYSTORE_MODULE, 0, 0);
124     if(module == 0) {
125         log_error("could not get module %s from context\n", IETF_KEYSTORE_MODULE);
126         return NTS_ERR_FAILED;
127     }
128     
129     struct lyd_node *keystore_node = 0;
130     keystore_node = lyd_new(NULL, module, "keystore");
131     if(keystore_node == 0) {
132         log_error("could not create a new lyd_node\n");
133         return NTS_ERR_FAILED;
134     }
135
136     sprintf(xpath, IETF_KEYSTORE_ASYMETRIC_KEY_SCHEMA_XPATH"/algorithm", KS_KEY_NAME);
137     rcl = lyd_new_path(keystore_node, 0, xpath, "rsa2048", 0, LYD_PATH_OPT_NOPARENTRET);
138     if(rcl == 0) {
139         log_error("could not created yang path\n");
140         return NTS_ERR_FAILED;
141     }
142
143     char *private_key = read_key(SERVER_PRIVATE_KEY_PATH);
144     if(private_key == 0) {
145         log_error("could not read the private key from path=%s\n", SERVER_PRIVATE_KEY_PATH);
146         return NTS_ERR_FAILED;
147     }
148     log_add_verbose(2, "Private Key that was built: \n%s\n", private_key);
149
150     sprintf(xpath, IETF_KEYSTORE_ASYMETRIC_KEY_SCHEMA_XPATH"/private-key", KS_KEY_NAME);
151     rcl = lyd_new_path(keystore_node, 0, xpath, private_key, 0, LYD_PATH_OPT_NOPARENTRET);
152     if(rcl == 0) {
153         log_error("could not created yang path\n");
154         return NTS_ERR_FAILED;
155     }
156
157     free(private_key);
158
159     char *public_key = read_key(SERVER_PUBLIC_KEY_PATH);
160     if(public_key == 0) {
161         log_error("could not read the public key from path=%s\n", SERVER_PUBLIC_KEY_PATH);
162         return NTS_ERR_FAILED;
163     }
164     log_add_verbose(2, "Public Key that was built: \n%s\n", public_key);
165
166     sprintf(xpath, IETF_KEYSTORE_ASYMETRIC_KEY_SCHEMA_XPATH"/public-key", KS_KEY_NAME);
167     rcl = lyd_new_path(keystore_node, 0, xpath, public_key, 0, LYD_PATH_OPT_NOPARENTRET);
168     if(rcl == 0) {
169         log_error("could not created yang path\n");
170         return NTS_ERR_FAILED;
171     }
172
173     free(public_key);
174
175     char *certificate = read_key(SERVER_CERT_PATH);
176     if(certificate == 0) {
177         log_error("could not read the certificate from path=%s\n", SERVER_CERT_PATH);
178         return NTS_ERR_FAILED;
179     }
180     log_add_verbose(2, "Certificate that was built: \n%s\n", certificate);
181
182     sprintf(xpath, IETF_KEYSTORE_ASYMETRIC_KEY_SCHEMA_XPATH"/certificates/certificate[name='%s']/cert", KS_KEY_NAME, KS_CERT_NAME);
183     rcl = lyd_new_path(keystore_node, 0, xpath, certificate, 0, LYD_PATH_OPT_NOPARENTRET);
184     if(rcl == 0) {
185         log_error("could not created yang path\n");
186         return NTS_ERR_FAILED;
187     }
188
189     free(certificate);
190
191     rc = sr_edit_batch(session, keystore_node, "replace");
192     if(rc != SR_ERR_OK) {
193         log_error("could not edit batch on datastore\n");
194         return NTS_ERR_FAILED;
195     }
196
197     rc = sr_validate(session, IETF_KEYSTORE_MODULE, 0);
198     if(rc != SR_ERR_OK) {
199         struct ly_err_item *err = ly_err_first(session_context);
200         log_error("sr_validate issues on STARTUP: %s\n", err->msg);
201         return false;
202     }
203
204     rc = sr_apply_changes(session, 0, 0);
205     if(rc != SR_ERR_OK) {
206         log_error("could not apply changes on datastore\n");
207         return NTS_ERR_FAILED;
208     }
209     
210     return NTS_ERR_OK;
211 }
212
213 static int load_trusted_certificates(sr_session_ctx_t *session) {
214     assert(session);
215
216     int rc = NTS_ERR_OK;
217     struct lyd_node *rcl = 0;
218
219     struct lyd_node *trusted_certificate_node = 0;
220     struct lys_module *module;
221     module = (struct lys_module *)ly_ctx_get_module(session_context, IETF_TRUSTSTORE_MODULE, 0, 0);
222     if(module == 0) {
223         log_error("could not get module %s from context\n", IETF_TRUSTSTORE_MODULE);
224         return NTS_ERR_FAILED;
225     }
226
227     trusted_certificate_node = lyd_new(NULL, module, "truststore");
228     if(trusted_certificate_node == 0) {
229         log_error("could not create a new lyd_node\n");
230         return NTS_ERR_FAILED;
231     }
232
233     char *client_cert = read_key(CLIENT_CERT_PATH);
234     rcl = lyd_new_path(trusted_certificate_node, 0, IETF_TRUSTSTORE_CERT_PATH_SCHEMA_XPATH, client_cert, 0, LYD_PATH_OPT_NOPARENTRET);
235     if(rcl == 0) {
236         log_error("could not created yang path\n");
237         return NTS_ERR_FAILED;
238     }
239     free(client_cert);
240
241     char *ca_cert = read_key(CA_CERT_PATH);
242     rcl = lyd_new_path(trusted_certificate_node, 0, IETF_TRUSTSTORE_CA_CERT_PATH_SCHEMA_XPATH, ca_cert, 0, LYD_PATH_OPT_NOPARENTRET);
243     if(rcl == 0) {
244         log_error("could not created yang path\n");
245         return NTS_ERR_FAILED;
246     }
247     free(ca_cert);
248
249     rc = sr_edit_batch(session, trusted_certificate_node, "replace");
250     if(rc != SR_ERR_OK) {
251         log_error("could not edit batch on datastore\n");
252         return NTS_ERR_FAILED;
253     }
254
255     rc = sr_validate(session, IETF_TRUSTSTORE_MODULE, 0);
256     if(rc != SR_ERR_OK) {
257         struct ly_err_item *err = ly_err_first(session_context);
258         log_error("sr_validate issues: %s\n", err->msg);
259         return NTS_ERR_FAILED;
260     }
261
262     rc = sr_apply_changes(session, 0, 0);
263     if(rc != SR_ERR_OK) {
264         log_error("could not apply changes on datastore\n");
265         return NTS_ERR_FAILED;
266     }
267  
268     return NTS_ERR_OK;
269 }
270
271 static int configure_nacm(sr_session_ctx_t *session) {
272     assert(session);
273
274     int rc = NTS_ERR_OK;
275     struct lyd_node *rcl = 0;
276
277     struct lys_module *module = 0;
278     module = (struct lys_module *) ly_ctx_get_module(session_context, IETF_NETCONF_ACM_MODULE, 0, 0);
279     if(module == 0) {
280         log_error("could not get module %s from context\n", IETF_NETCONF_ACM_MODULE);
281         return NTS_ERR_FAILED;
282     }
283
284     struct lyd_node *nacm_node = 0;
285     nacm_node = lyd_new(NULL, module, "nacm");
286     if(nacm_node == 0) {
287         log_error("could not create a new lyd_node\n");
288         return NTS_ERR_FAILED;
289     }
290
291     rcl = lyd_new_path(nacm_node, 0, IETF_NETCONF_ACM_ENABLE_NACM_SCHEMA_XPATH, "true", 0, LYD_PATH_OPT_NOPARENTRET);
292     if(rcl == 0) {
293         log_error("could not create yang path\n");
294         return NTS_ERR_FAILED;
295     }
296
297     // we hardcoded here the username to be used
298     rcl = lyd_new_path(nacm_node, 0, IETF_NETCONF_ACM_GROUPS_SCHEMA_XPATH"/group[name='sudo']/user-name", "netconf", 0, LYD_PATH_OPT_NOPARENTRET);
299     if(rcl == 0) {
300         log_error("could not create yang path\n");
301         return NTS_ERR_FAILED;
302     }
303
304     rcl = lyd_new_path(nacm_node, 0, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/group", "sudo", 0, LYD_PATH_OPT_NOPARENTRET);
305     if(rcl == 0) {
306         log_error("could not create yang path\n");
307         return NTS_ERR_FAILED;
308     }
309
310     rcl = lyd_new_path(nacm_node, 0, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/rule[name='allow-all-sudo']/module-name", "*", 0, LYD_PATH_OPT_NOPARENTRET);
311     if(rcl == 0) {
312         log_error("could not create yang path\n");
313         return NTS_ERR_FAILED;
314     }
315
316     rcl = lyd_new_path(nacm_node, 0, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/rule[name='allow-all-sudo']/path", "/", 0, LYD_PATH_OPT_NOPARENTRET);
317     if(rcl == 0) {
318         log_error("could not create yang path\n");
319         return NTS_ERR_FAILED;
320     }
321
322     rcl = lyd_new_path(nacm_node, 0, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/rule[name='allow-all-sudo']/access-operations", "*", 0, LYD_PATH_OPT_NOPARENTRET);
323     if(rcl == 0) {
324         log_error("could not create yang path\n");
325         return NTS_ERR_FAILED;
326     }
327
328     rcl = lyd_new_path(nacm_node, 0, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/rule[name='allow-all-sudo']/action", "permit", 0, LYD_PATH_OPT_NOPARENTRET);
329     if(rcl == 0) {
330         log_error("could not create yang path\n");
331         return NTS_ERR_FAILED;
332     }
333
334     rcl = lyd_new_path(nacm_node, 0, IETF_NETCONF_ACM_RULE_LIST_SCHEMA_XPATH"[name='sudo-rules']/rule[name='allow-all-sudo']/comment", "Corresponds all the rules under the sudo group as defined in O-RAN.WG4.MP.0-v05.00", 0, LYD_PATH_OPT_NOPARENTRET);
335     if(rcl == 0) {
336         log_error("could not create yang path\n");
337         return NTS_ERR_FAILED;
338     }
339
340     rc = sr_edit_batch(session, nacm_node, "replace");
341     if(rc != SR_ERR_OK) {
342         log_error("could not edit batch on datastore\n");
343         return NTS_ERR_FAILED;
344     }
345
346     rc = sr_validate(session, IETF_NETCONF_ACM_MODULE, 0);
347     if(rc != SR_ERR_OK) {
348         struct ly_err_item *err = ly_err_first(session_context);
349         log_error("sr_validate issues: %s\n", err->msg);
350         return NTS_ERR_FAILED;
351     }
352
353     rc = sr_apply_changes(session, 0, 0);
354     if(rc != SR_ERR_OK) {
355         log_error("could not apply changes on datastore\n");
356         return NTS_ERR_FAILED;
357     }
358     
359     return NTS_ERR_OK;
360 }
361
362 static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_connections) {
363     assert(netconf_node);
364
365     char xpath[500];
366     char local_ip[30];
367     struct lyd_node *rcl = 0;
368
369     
370     if(framework_environment.settings.ip_v6_enabled) {
371         sprintf(local_ip, "::");
372     }
373     else {
374         sprintf(local_ip, "0.0.0.0");
375     } 
376
377     char *public_ssh_key = read_key(SERVER_PUBLIC_SSH_KEY_PATH);
378     if(public_ssh_key == 0) {
379         log_error("could not read the public ssh key from file %s\n", SERVER_PUBLIC_SSH_KEY_PATH);
380         return NTS_ERR_FAILED;
381     }
382
383     char *ssh_key_string;
384
385     ssh_key_string = strtok(public_ssh_key, " ");
386     ssh_key_string = strtok(NULL, " ");
387
388     for(int i = 0; i < ssh_connections; ++i) {
389         char endpoint_name[100];
390         sprintf(endpoint_name, "mng-ssh-%d", i);
391
392         sprintf(xpath, IETF_NETCONF_SERVER_SSH_TCP_SERVER_PARAM_SCHEMA_XPATH"/local-address", endpoint_name);
393         rcl = lyd_new_path(netconf_node, 0, xpath, local_ip, 0, LYD_PATH_OPT_NOPARENTRET);
394         if(rcl == 0) {
395             log_error("could not created yang path\n");
396             return NTS_ERR_FAILED;
397         }
398
399         char local_port[10];
400         sprintf(local_port, "%d", nc_config_netconf_port++);
401         sprintf(xpath, IETF_NETCONF_SERVER_SSH_TCP_SERVER_PARAM_SCHEMA_XPATH"/local-port", endpoint_name);
402         rcl = lyd_new_path(netconf_node, 0, xpath, local_port, 0, LYD_PATH_OPT_NOPARENTRET);
403         if(rcl == 0) {
404             log_error("could not created yang path\n");
405             return NTS_ERR_FAILED;
406         }
407
408         sprintf(xpath, IETF_NETCONF_SERVER_SSH_TCP_SERVER_PARAM_SCHEMA_XPATH"/keepalives/idle-time", endpoint_name);
409         rcl = lyd_new_path(netconf_node, 0, xpath, "1", 0, LYD_PATH_OPT_NOPARENTRET);
410         if(rcl == 0) {
411             log_error("could not created yang path\n");
412             return NTS_ERR_FAILED;
413         }
414
415         sprintf(xpath, IETF_NETCONF_SERVER_SSH_TCP_SERVER_PARAM_SCHEMA_XPATH"/keepalives/max-probes", endpoint_name);
416         rcl = lyd_new_path(netconf_node, 0, xpath, "10", 0, LYD_PATH_OPT_NOPARENTRET);
417         if(rcl == 0) {
418             log_error("could not created yang path\n");
419             return NTS_ERR_FAILED;
420         }
421
422         sprintf(xpath, IETF_NETCONF_SERVER_SSH_TCP_SERVER_PARAM_SCHEMA_XPATH"/keepalives/probe-interval", endpoint_name);
423         rcl = lyd_new_path(netconf_node, 0, xpath, "5", 0, LYD_PATH_OPT_NOPARENTRET);
424         if(rcl == 0) {
425             log_error("could not created yang path\n");
426             return NTS_ERR_FAILED;
427         }
428
429         sprintf(xpath, IETF_NETCONF_SERVER_SSH_SERVER_PARAM_SCHEMA_XPATH"/server-identity/host-key[name='default-key']/public-key/keystore-reference", endpoint_name);
430         rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
431         if(rcl == 0) {
432             log_error("could not created yang path\n");
433             return NTS_ERR_FAILED;
434         }
435
436         sprintf(xpath, IETF_NETCONF_SERVER_SSH_SERVER_PARAM_SCHEMA_XPATH"/client-authentication/supported-authentication-methods/publickey", endpoint_name);
437         rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
438         if(rcl == 0) {
439             log_error("could not created yang path\n");
440             return NTS_ERR_FAILED;
441         }
442
443         sprintf(xpath, IETF_NETCONF_SERVER_SSH_SERVER_PARAM_SCHEMA_XPATH"/client-authentication/supported-authentication-methods/passsword", endpoint_name);
444         rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
445         if(rcl == 0) {
446             log_error("could not created yang path\n");
447             return NTS_ERR_FAILED;
448         }
449
450         sprintf(xpath, IETF_NETCONF_SERVER_SSH_SERVER_PARAM_SCHEMA_XPATH"/client-authentication/supported-authentication-methods/other", endpoint_name);
451         rcl = lyd_new_path(netconf_node, 0, xpath, "interactive", 0, LYD_PATH_OPT_NOPARENTRET);
452         if(rcl == 0) {
453             log_error("could not created yang path\n");
454             return NTS_ERR_FAILED;
455         }
456
457         sprintf(xpath, IETF_NETCONF_SERVER_SSH_SERVER_PARAM_SCHEMA_XPATH"/client-authentication/users/user[name='netconf']/authorized-key[name='%s']/algorithm", endpoint_name, KS_KEY_NAME);
458         rcl = lyd_new_path(netconf_node, 0, xpath, "ssh-rsa", 0, LYD_PATH_OPT_NOPARENTRET);
459         if(rcl == 0) {
460             log_error("could not created yang path\n");
461             return NTS_ERR_FAILED;
462         }
463
464         sprintf(xpath, IETF_NETCONF_SERVER_SSH_SERVER_PARAM_SCHEMA_XPATH"/client-authentication/users/user[name='netconf']/authorized-key[name='%s']/key-data", endpoint_name, KS_KEY_NAME);
465         rcl = lyd_new_path(netconf_node, 0, xpath, ssh_key_string, 0, LYD_PATH_OPT_NOPARENTRET);
466         if(rcl == 0) {
467             log_error("could not created yang path\n");
468             return NTS_ERR_FAILED;
469         }
470     } 
471
472     free(public_ssh_key);
473
474     return NTS_ERR_OK;
475 }
476
477 static int create_tls_listen_endpoints(struct lyd_node *netconf_node, int tls_connections) {
478     assert(netconf_node);
479
480     struct lyd_node *rcl = 0;
481     char xpath[500];
482     char local_ip[30];
483
484     if(framework_environment.settings.ip_v6_enabled) {
485         sprintf(local_ip, "::");
486     }
487     else {
488         sprintf(local_ip, "0.0.0.0");
489     } 
490
491     for(int i = 0; i < tls_connections + 1; ++i) {
492         char endpoint_name[100];
493         char local_port[10];
494         
495         
496
497         if(i == tls_connections) {
498             //manager connection port
499             sprintf(endpoint_name, "manger-tls-internal");
500             sprintf(local_port, "%d", CLIENT_CONFIG_TLS_PORT);
501         }
502         else {
503             sprintf(endpoint_name, "mng-tls-%d", i);
504             sprintf(local_port, "%d", nc_config_netconf_port++);
505         }
506
507         sprintf(xpath, IETF_NETCONF_SERVER_TLS_TCP_SERVER_PARAM_SCHEMA_XPATH"/local-address", endpoint_name);
508         rcl = lyd_new_path(netconf_node, 0, xpath, local_ip, 0, LYD_PATH_OPT_NOPARENTRET);
509         if(rcl == 0) {
510             log_error("could not created yang path\n");
511             return NTS_ERR_FAILED;
512         }
513
514         sprintf(xpath, IETF_NETCONF_SERVER_TLS_TCP_SERVER_PARAM_SCHEMA_XPATH"/local-port", endpoint_name);
515         rcl = lyd_new_path(netconf_node, 0, xpath, local_port, 0, LYD_PATH_OPT_NOPARENTRET);
516         if(rcl == 0) {
517             log_error("could not created yang path\n");
518             return NTS_ERR_FAILED;
519         }
520
521         sprintf(xpath, IETF_NETCONF_SERVER_TLS_TCP_SERVER_PARAM_SCHEMA_XPATH"/keepalives/idle-time", endpoint_name);
522         rcl = lyd_new_path(netconf_node, 0, xpath, "1", 0, LYD_PATH_OPT_NOPARENTRET);
523         if(rcl == 0) {
524             log_error("could not created yang path\n");
525             return NTS_ERR_FAILED;
526         }
527
528         sprintf(xpath, IETF_NETCONF_SERVER_TLS_TCP_SERVER_PARAM_SCHEMA_XPATH"/keepalives/max-probes", endpoint_name);
529         rcl = lyd_new_path(netconf_node, 0, xpath, "10", 0, LYD_PATH_OPT_NOPARENTRET);
530         if(rcl == 0) {
531             log_error("could not created yang path\n");
532             return NTS_ERR_FAILED;
533         }
534
535         sprintf(xpath, IETF_NETCONF_SERVER_TLS_TCP_SERVER_PARAM_SCHEMA_XPATH"/keepalives/probe-interval", endpoint_name);
536         rcl = lyd_new_path(netconf_node, 0, xpath, "5", 0, LYD_PATH_OPT_NOPARENTRET);
537         if(rcl == 0) {
538             log_error("could not created yang path\n");
539             return NTS_ERR_FAILED;
540         }
541
542         sprintf(xpath, IETF_NETCONF_SERVER_TLS_SERVER_PARAM_SCHEMA_XPATH"/server-identity/keystore-reference/asymmetric-key", endpoint_name);
543         rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
544         if(rcl == 0) {
545             log_error("could not created yang path\n");
546             return NTS_ERR_FAILED;
547         }
548
549         sprintf(xpath, IETF_NETCONF_SERVER_TLS_SERVER_PARAM_SCHEMA_XPATH"/server-identity/keystore-reference/certificate", endpoint_name);
550         rcl = lyd_new_path(netconf_node, 0, xpath, KS_CERT_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
551         if(rcl == 0) {
552             log_error("could not created yang path\n");
553             return NTS_ERR_FAILED;
554         }
555
556         sprintf(xpath, IETF_NETCONF_SERVER_TLS_SERVER_PARAM_SCHEMA_XPATH"/client-authentication/required", endpoint_name);
557         rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
558         if(rcl == 0) {
559             log_error("could not created yang path\n");
560             return NTS_ERR_FAILED;
561         }
562
563         sprintf(xpath, IETF_NETCONF_SERVER_TLS_SERVER_PARAM_SCHEMA_XPATH"/client-authentication/ca-certs", endpoint_name);
564         rcl = lyd_new_path(netconf_node, 0, xpath, "cacerts", 0, LYD_PATH_OPT_NOPARENTRET);
565         if(rcl == 0) {
566             log_error("could not created yang path\n");
567             return NTS_ERR_FAILED;
568         }
569
570         sprintf(xpath, IETF_NETCONF_SERVER_TLS_SERVER_PARAM_SCHEMA_XPATH"/client-authentication/client-certs", endpoint_name);
571         rcl = lyd_new_path(netconf_node, 0, xpath, "clientcerts", 0, LYD_PATH_OPT_NOPARENTRET);
572         if(rcl == 0) {
573             log_error("could not created yang path\n");
574             return NTS_ERR_FAILED;
575         }
576
577         sprintf(xpath, IETF_NETCONF_SERVER_TLS_SERVER_PARAM_SCHEMA_XPATH"/client-authentication/cert-maps/cert-to-name[id='1']/fingerprint", endpoint_name);
578         rcl = lyd_new_path(netconf_node, 0, xpath, "02:E9:38:1F:F6:8B:62:DE:0A:0B:C5:03:81:A8:03:49:A0:00:7F:8B:F3", 0, LYD_PATH_OPT_NOPARENTRET);
579         if(rcl == 0) {
580             log_error("could not created yang path\n");
581             return NTS_ERR_FAILED;
582         }
583
584         sprintf(xpath, IETF_NETCONF_SERVER_TLS_SERVER_PARAM_SCHEMA_XPATH"/client-authentication/cert-maps/cert-to-name[id='1']/map-type", endpoint_name);
585         rcl = lyd_new_path(netconf_node, session_context, xpath, "ietf-x509-cert-to-name:specified", 0, LYD_PATH_OPT_NOPARENTRET);
586         if(rcl == 0) {
587             log_error("could not created yang path\n");
588             return NTS_ERR_FAILED;
589         }
590
591         sprintf(xpath, IETF_NETCONF_SERVER_TLS_SERVER_PARAM_SCHEMA_XPATH"/client-authentication/cert-maps/cert-to-name[id='1']/name", endpoint_name);
592         rcl = lyd_new_path(netconf_node, 0, xpath, "netconf", 0, LYD_PATH_OPT_NOPARENTRET);
593         if(rcl == 0) {
594             log_error("could not created yang path\n");
595             return NTS_ERR_FAILED;
596         }
597     }
598
599     return NTS_ERR_OK;
600 }
601
602 static int configure_endpoints_connections(sr_session_ctx_t *session) {
603     assert(session);
604
605     int rc = NTS_ERR_OK;
606
607     struct lys_module *module = 0;
608     module = (struct lys_module *)ly_ctx_get_module(session_context, IETF_NETCONF_SERVER_MODULE, 0, 0);
609     if(module == 0) {
610         log_error("could not get module %s from context\n", IETF_NETCONF_SERVER_MODULE);
611         return NTS_ERR_FAILED;
612     }
613
614
615     struct lyd_node *netconf_node = 0;
616     netconf_node = lyd_new_path(NULL, session_context, IETF_NETCONF_SERVER_SCHEMA_XPATH, 0, 0, 0);
617     if(netconf_node == 0) {
618         log_error("could not create a new lyd_node\n");
619         return NTS_ERR_FAILED;
620     }
621
622     // create the SSH endpoints in ietf-netconf-server
623     int ssh_connections = 0;
624     if(framework_arguments.nts_mode == NTS_MODE_MANAGER) {
625         ssh_connections = 1;
626     }
627     else {
628         ssh_connections = framework_environment.settings.ssh_connections;
629     }
630
631     if(ssh_connections + framework_environment.settings.tls_connections == 0) {
632         log_error("ssh_connections + tls_connections must be at least 1\n");
633         return NTS_ERR_FAILED;
634     }
635
636     rc = create_ssh_listen_endpoints(netconf_node, ssh_connections);
637     if(rc != NTS_ERR_OK) {
638         log_error("could not create %d SSH Listen endpoints on the NETCONF Server\n", ssh_connections);
639         return NTS_ERR_FAILED;
640     }
641
642     // create the TLS endpoints in ietf-netconf-server
643     if(framework_arguments.nts_mode != NTS_MODE_MANAGER) {
644         rc = create_tls_listen_endpoints(netconf_node, framework_environment.settings.tls_connections);
645         if(rc != NTS_ERR_OK) {
646             log_error("could not create %d TLS Listen endpoints on the NETCONF Server\n", framework_environment.settings.tls_connections);
647             return NTS_ERR_FAILED;
648         }
649     }
650     
651     rc = sr_edit_batch(session, netconf_node, "replace");
652     if(rc != SR_ERR_OK) {
653         log_error("could not edit batch on datastore\n");
654         return NTS_ERR_FAILED;
655     }
656
657     rc = sr_validate(session, IETF_NETCONF_SERVER_MODULE, 0);
658     if(rc != SR_ERR_OK) {
659         struct ly_err_item *err = ly_err_first(session_context);
660         log_error("sr_validate issues on STARTUP: %s\n", err->msg);
661         return NTS_ERR_FAILED;
662     }
663
664     rc = sr_apply_changes(session, 0, 0);
665     if(rc != SR_ERR_OK) {
666         log_error("could not apply changes on datastore\n");
667         return NTS_ERR_FAILED;
668     }
669     
670     return NTS_ERR_OK;
671 }