Bugfix for SIM-64.
[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/framework.h"
33
34 #define GEN_KEY_SCRIPT                              "/home/netconf/.ssh/generate-ssh-keys.sh"
35 #define KS_CERT_NAME                                "melacon_server_cert"
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 SERVER_CERT_PATH                            "/home/netconf/.ssh/melacon.server.crt"
39 #define CA_CERT_PATH                                "/home/netconf/.ssh/ca.pem"
40
41 static int nc_config_netconf_port = STANDARD_NETCONF_PORT;
42
43 static int load_ssh_keys(sr_session_ctx_t *session);
44 static int load_trusted_certificates(sr_session_ctx_t *session);
45 static int configure_nacm(sr_session_ctx_t *session);
46 static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_connections);
47 static int create_tls_listen_endpoints(struct lyd_node *netconf_node, int tls_connections);
48 static int configure_endpoints_connections(sr_session_ctx_t *session);
49
50 int netconf_configure(void) {
51     int rc = NTS_ERR_OK;
52
53     nc_config_netconf_port = STANDARD_NETCONF_PORT;
54
55     //check if was already ran
56     sr_val_t *val = 0;
57     rc = sr_get_item(session_running, "/ietf-keystore:keystore", 0, &val);
58     if(rc != SR_ERR_OK) {
59         log_error("sr_get_item failed\n");
60         return NTS_ERR_FAILED;
61     }
62     
63     bool already_done = (val->dflt == false);
64     sr_free_val(val);
65     val = 0;
66     if(already_done) {
67         log_add_verbose(2, "netconf_configure() already ran, skipping...\n");
68         return NTS_ERR_OK;
69     }
70
71     // generate and load private keys
72     log_add_verbose(1, "ietf-keystore startup datastore configuration...");
73     rc = load_ssh_keys(session_running);
74     if(rc != 0) {
75         log_error("could not load SSH keys\n");
76         return NTS_ERR_FAILED;
77     }
78     log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
79
80     // load trusted certificates
81     log_add_verbose(1, "ietf-truststore startup datastore configuration...");
82     rc = load_trusted_certificates(session_running);
83     if(rc != 0) {
84         log_error("could not load trusted certificates\n");
85         return NTS_ERR_FAILED;
86     }
87     log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
88
89     // configuring NACM
90     log_add_verbose(1, "configuring NACM...");
91     rc = configure_nacm(session_running);
92     if(rc != 0) {
93         log_error("could not configure NACM\n");
94         return NTS_ERR_FAILED;
95     }
96     log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
97
98     // configure SSH connections
99     log_add_verbose(1, "Configuring connection endpoints...");
100     rc = configure_endpoints_connections(session_running);
101     if(rc != 0) {
102         log_error("could not configure endpoint connections forNETCONF Server\n");
103         return NTS_ERR_FAILED;
104     }
105     log_add(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
106
107     return NTS_ERR_OK;
108 }
109
110 static int load_ssh_keys(sr_session_ctx_t *session) {
111     assert(session);
112
113     int rc = NTS_ERR_OK;
114     char xpath[500];
115     struct lyd_node *rcl = 0;
116
117     rc = system(GEN_KEY_SCRIPT);
118     if(rc != 0) {
119         log_error("could not generate the SSH keys\n");
120         return NTS_ERR_FAILED;
121     }
122
123     struct lys_module *module;
124     module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-keystore", 0, 0);
125     if(module == 0) {
126         log_error("could not get module %s from context\n", "ietf-keystore");
127         return NTS_ERR_FAILED;
128     }
129     
130     struct lyd_node *keystore_node = 0;
131     keystore_node = lyd_new(NULL, module, "keystore");
132     if(keystore_node == 0) {
133         log_error("could not create a new lyd_node\n");
134         return NTS_ERR_FAILED;
135     }
136
137     sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/algorithm", KS_KEY_NAME);
138     rcl = lyd_new_path(keystore_node, 0, xpath, "rsa2048", 0, LYD_PATH_OPT_NOPARENTRET);
139     if(rcl == 0) {
140         log_error("could not created yang path\n");
141         return NTS_ERR_FAILED;
142     }
143
144     char *private_key = read_key(SERVER_PRIVATE_KEY_PATH);
145     if(private_key == 0) {
146         log_error("could not read the private key from path=%s\n", SERVER_PRIVATE_KEY_PATH);
147         return NTS_ERR_FAILED;
148     }
149     log_add_verbose(2, "Private Key that was built: \n%s\n", private_key);
150
151     sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/private-key", KS_KEY_NAME);
152     rcl = lyd_new_path(keystore_node, 0, xpath, private_key, 0, LYD_PATH_OPT_NOPARENTRET);
153     if(rcl == 0) {
154         log_error("could not created yang path\n");
155         return NTS_ERR_FAILED;
156     }
157
158     free(private_key);
159
160     char *public_key = read_key(SERVER_PUBLIC_KEY_PATH);
161     if(public_key == 0) {
162         log_error("could not read the public key from path=%s\n", SERVER_PUBLIC_KEY_PATH);
163         return NTS_ERR_FAILED;
164     }
165     log_add_verbose(2, "Public Key that was built: \n%s\n", public_key);
166
167     sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/public-key", KS_KEY_NAME);
168     rcl = lyd_new_path(keystore_node, 0, xpath, public_key, 0, LYD_PATH_OPT_NOPARENTRET);
169     if(rcl == 0) {
170         log_error("could not created yang path\n");
171         return NTS_ERR_FAILED;
172     }
173
174     free(public_key);
175
176     char *certificate = read_key(SERVER_CERT_PATH);
177     if(certificate == 0) {
178         log_error("could not read the certificate from path=%s\n", SERVER_CERT_PATH);
179         return NTS_ERR_FAILED;
180     }
181     log_add_verbose(2, "Certificate that was built: \n%s\n", certificate);
182
183     sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/certificates/certificate[name='%s']/cert", KS_KEY_NAME, KS_CERT_NAME);
184     rcl = lyd_new_path(keystore_node, 0, xpath, certificate, 0, LYD_PATH_OPT_NOPARENTRET);
185     if(rcl == 0) {
186         log_error("could not created yang path\n");
187         return NTS_ERR_FAILED;
188     }
189
190     free(certificate);
191
192     rc = sr_edit_batch(session, keystore_node, "replace");
193     if(rc != SR_ERR_OK) {
194         log_error("could not edit batch on datastore\n");
195         return NTS_ERR_FAILED;
196     }
197
198     rc = sr_validate(session, "ietf-keystore", 0);
199     if(rc != SR_ERR_OK) {
200         struct ly_err_item *err = ly_err_first(session_context);
201         log_error("sr_validate issues on STARTUP: %s\n", err->msg);
202         return false;
203     }
204
205     rc = sr_apply_changes(session, 0, 0);
206     if(rc != SR_ERR_OK) {
207         log_error("could not apply changes on datastore\n");
208         return NTS_ERR_FAILED;
209     }
210     
211     return NTS_ERR_OK;
212 }
213
214 static int load_trusted_certificates(sr_session_ctx_t *session) {
215     assert(session);
216
217     int rc = NTS_ERR_OK;
218     struct lyd_node *rcl = 0;
219
220     struct lyd_node *trusted_certificate_node = 0;
221     struct lys_module *module;
222     module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-truststore", 0, 0);
223     if(module == 0) {
224         log_error("could not get module %s from context\n", "ietf-truststore");
225         return NTS_ERR_FAILED;
226     }
227
228     trusted_certificate_node = lyd_new(NULL, module, "truststore");
229     if(trusted_certificate_node == 0) {
230         log_error("could not create a new lyd_node\n");
231         return NTS_ERR_FAILED;
232     }
233
234     char xpath[500];
235
236     sprintf(xpath, "/ietf-truststore:truststore/certificates[name='clientcerts']/certificate[name='clientcert']/cert");
237     char *client_cert = read_key(CLIENT_CERT_PATH);
238     rcl = lyd_new_path(trusted_certificate_node, 0, xpath, client_cert, 0, LYD_PATH_OPT_NOPARENTRET);
239     if(rcl == 0) {
240         log_error("could not created yang path\n");
241         return NTS_ERR_FAILED;
242     }
243     free(client_cert);
244
245     sprintf(xpath, "/ietf-truststore:truststore/certificates[name='cacerts']/certificate[name='cacert']/cert");
246     char *ca_cert = read_key(CA_CERT_PATH);
247     rcl = lyd_new_path(trusted_certificate_node, 0, xpath, ca_cert, 0, LYD_PATH_OPT_NOPARENTRET);
248     if(rcl == 0) {
249         log_error("could not created yang path\n");
250         return NTS_ERR_FAILED;
251     }
252     free(ca_cert);
253
254     rc = sr_edit_batch(session, trusted_certificate_node, "replace");
255     if(rc != SR_ERR_OK) {
256         log_error("could not edit batch on datastore\n");
257         return NTS_ERR_FAILED;
258     }
259
260     rc = sr_validate(session, "ietf-truststore", 0);
261     if(rc != SR_ERR_OK) {
262         struct ly_err_item *err = ly_err_first(session_context);
263         log_error("sr_validate issues on STARTUP: %s\n", err->msg);
264         return NTS_ERR_FAILED;
265     }
266
267     rc = sr_apply_changes(session, 0, 0);
268     if(rc != SR_ERR_OK) {
269         log_error("could not apply changes on datastore\n");
270         return NTS_ERR_FAILED;
271     }
272  
273     return NTS_ERR_OK;
274 }
275
276 static int configure_nacm(sr_session_ctx_t *session) {
277     assert(session);
278
279     int rc = NTS_ERR_OK;
280     struct lyd_node *rcl = 0;
281     char xpath[100];
282
283     struct lys_module *module = 0;
284     module = (struct lys_module *) ly_ctx_get_module(session_context, "ietf-netconf-acm", 0, 0);
285     if(module == 0) {
286         log_error("could not get module %s from context\n", "ietf-netconf-acm");
287         return NTS_ERR_FAILED;
288     }
289
290     struct lyd_node *nacm_node = 0;
291     nacm_node = lyd_new(NULL, module, "nacm");
292     if(nacm_node == 0) {
293         log_error("could not create a new lyd_node\n");
294         return NTS_ERR_FAILED;
295     }
296
297     sprintf(xpath, "/ietf-netconf-acm:nacm/enable-nacm");
298     rcl = lyd_new_path(nacm_node, 0, xpath, "true", 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     sprintf(xpath, "/ietf-netconf-acm:nacm/groups/group[name='sudo']/user-name");
305     // we hardcoded here the username to be used
306     rcl = lyd_new_path(nacm_node, 0, xpath, "netconf", 0, LYD_PATH_OPT_NOPARENTRET);
307     if(rcl == 0) {
308         log_error("could not create yang path\n");
309         return NTS_ERR_FAILED;
310     }
311
312     sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/group");
313     rcl = lyd_new_path(nacm_node, 0, xpath, "sudo", 0, LYD_PATH_OPT_NOPARENTRET);
314     if(rcl == 0) {
315         log_error("could not create yang path\n");
316         return NTS_ERR_FAILED;
317     }
318
319     sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/rule[name='allow-all-sudo']/module-name");
320     rcl = lyd_new_path(nacm_node, 0, xpath, "*", 0, LYD_PATH_OPT_NOPARENTRET);
321     if(rcl == 0) {
322         log_error("could not create yang path\n");
323         return NTS_ERR_FAILED;
324     }
325
326     sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/rule[name='allow-all-sudo']/path");
327     rcl = lyd_new_path(nacm_node, 0, xpath, "/", 0, LYD_PATH_OPT_NOPARENTRET);
328     if(rcl == 0) {
329         log_error("could not create yang path\n");
330         return NTS_ERR_FAILED;
331     }
332
333     sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/rule[name='allow-all-sudo']/access-operations");
334     rcl = lyd_new_path(nacm_node, 0, xpath, "*", 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     sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/rule[name='allow-all-sudo']/action");
341     rcl = lyd_new_path(nacm_node, 0, xpath, "permit", 0, LYD_PATH_OPT_NOPARENTRET);
342     if(rcl == 0) {
343         log_error("could not create yang path\n");
344         return NTS_ERR_FAILED;
345     }
346
347     sprintf(xpath, "/ietf-netconf-acm:nacm/rule-list[name='sudo-rules']/rule[name='allow-all-sudo']/comment");
348     rcl = lyd_new_path(nacm_node, 0, xpath, "Corresponds all the rules under the sudo group as defined in O-RAN.WG4.MP.0-v05.00", 0, LYD_PATH_OPT_NOPARENTRET);
349     if(rcl == 0) {
350         log_error("could not create yang path\n");
351         return NTS_ERR_FAILED;
352     }
353
354     rc = sr_edit_batch(session, nacm_node, "replace");
355     if(rc != SR_ERR_OK) {
356         log_error("could not edit batch on datastore\n");
357         return NTS_ERR_FAILED;
358     }
359
360     rc = sr_validate(session, "ietf-netconf-acm", 0);
361     if(rc != SR_ERR_OK) {
362         struct ly_err_item *err = ly_err_first(session_context);
363         log_error("sr_validate issues on STARTUP: %s\n", err->msg);
364         return NTS_ERR_FAILED;
365     }
366
367     rc = sr_apply_changes(session, 0, 0);
368     if(rc != SR_ERR_OK) {
369         log_error("could not apply changes on datastore\n");
370         return NTS_ERR_FAILED;
371     }
372     
373     return NTS_ERR_OK;
374 }
375
376 static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_connections) {
377     assert(netconf_node);
378
379     char xpath[500];
380     char local_ip[30];
381     struct lyd_node *rcl = 0;
382
383     
384     if(framework_environment.settings.ip_v6_enabled) {
385         sprintf(local_ip, "::");
386     }
387     else {
388         sprintf(local_ip, "0.0.0.0");
389     } 
390
391     char *public_ssh_key = read_key(SERVER_PUBLIC_SSH_KEY_PATH);
392     if(public_ssh_key == 0) {
393         log_error("could not read the public ssh key from file %s\n", SERVER_PUBLIC_SSH_KEY_PATH);
394         return NTS_ERR_FAILED;
395     }
396
397     char *ssh_key_string;
398
399     ssh_key_string = strtok(public_ssh_key, " ");
400     ssh_key_string = strtok(NULL, " ");
401
402     for(int i = 0; i < ssh_connections; ++i) {
403         char endpoint_name[100];
404         sprintf(endpoint_name, "mng-ssh-%d", i);
405
406         sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/local-address", endpoint_name);
407         rcl = lyd_new_path(netconf_node, 0, xpath, local_ip, 0, LYD_PATH_OPT_NOPARENTRET);
408         if(rcl == 0) {
409             log_error("could not created yang path\n");
410             return NTS_ERR_FAILED;
411         }
412
413         char local_port[10];
414         sprintf(local_port, "%d", nc_config_netconf_port++);
415         sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/local-port", endpoint_name);
416         rcl = lyd_new_path(netconf_node, 0, xpath, local_port, 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:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/idle-time", endpoint_name);
423         rcl = lyd_new_path(netconf_node, 0, xpath, "1", 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:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/max-probes", endpoint_name);
430         rcl = lyd_new_path(netconf_node, 0, xpath, "10", 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:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/probe-interval", endpoint_name);
437         rcl = lyd_new_path(netconf_node, 0, xpath, "5", 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:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/server-identity/host-key[name='default-key']/public-key/keystore-reference", endpoint_name);
444         rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 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:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/publickey", endpoint_name);
451         rcl = lyd_new_path(netconf_node, 0, xpath, "", 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:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/passsword", endpoint_name);
458         rcl = lyd_new_path(netconf_node, 0, xpath, "", 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:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/other", endpoint_name);
465         rcl = lyd_new_path(netconf_node, 0, xpath, "interactive", 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         sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/users/user[name='netconf']/authorized-key[name='%s']/algorithm", endpoint_name, KS_KEY_NAME);
472         rcl = lyd_new_path(netconf_node, 0, xpath, "ssh-rsa", 0, LYD_PATH_OPT_NOPARENTRET);
473         if(rcl == 0) {
474             log_error("could not created yang path\n");
475             return NTS_ERR_FAILED;
476         }
477
478         sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/users/user[name='netconf']/authorized-key[name='%s']/key-data", endpoint_name, KS_KEY_NAME);
479         rcl = lyd_new_path(netconf_node, 0, xpath, ssh_key_string, 0, LYD_PATH_OPT_NOPARENTRET);
480         if(rcl == 0) {
481             log_error("could not created yang path\n");
482             return NTS_ERR_FAILED;
483         }
484     } 
485
486     free(public_ssh_key);
487
488     return NTS_ERR_OK;
489 }
490
491 static int create_tls_listen_endpoints(struct lyd_node *netconf_node, int tls_connections) {
492     assert(netconf_node);
493
494     struct lyd_node *rcl = 0;
495     char xpath[500];
496     char local_ip[30];
497
498     if(framework_environment.settings.ip_v6_enabled) {
499         sprintf(local_ip, "::");
500     }
501     else {
502         sprintf(local_ip, "0.0.0.0");
503     } 
504
505     for(int i = 0; i < tls_connections + 1; ++i) {
506         char endpoint_name[100];
507         char local_port[10];
508         
509         
510
511         if(i == tls_connections) {
512             //manager connection port
513             sprintf(endpoint_name, "manger-tls-internal");
514             sprintf(local_port, "%d", CLIENT_CONFIG_TLS_PORT);
515         }
516         else {
517             sprintf(endpoint_name, "mng-tls-%d", i);
518             sprintf(local_port, "%d", nc_config_netconf_port++);
519         }
520
521         sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/local-address", endpoint_name);
522         rcl = lyd_new_path(netconf_node, 0, xpath, local_ip, 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:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/local-port", endpoint_name);
529         rcl = lyd_new_path(netconf_node, 0, xpath, local_port, 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:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/idle-time", endpoint_name);
536         rcl = lyd_new_path(netconf_node, 0, xpath, "1", 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:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/max-probes", endpoint_name);
543         rcl = lyd_new_path(netconf_node, 0, xpath, "10", 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:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/probe-interval", endpoint_name);
550         rcl = lyd_new_path(netconf_node, 0, xpath, "5", 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:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/server-identity/keystore-reference/asymmetric-key", endpoint_name);
557         rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 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:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/server-identity/keystore-reference/certificate", endpoint_name);
564         rcl = lyd_new_path(netconf_node, 0, xpath, KS_CERT_NAME, 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:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/required", endpoint_name);
571         rcl = lyd_new_path(netconf_node, 0, xpath, "", 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:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/ca-certs", endpoint_name);
578         rcl = lyd_new_path(netconf_node, 0, xpath, "cacerts", 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:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/client-certs", endpoint_name);
585         rcl = lyd_new_path(netconf_node, 0, xpath, "clientcerts", 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:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/fingerprint", endpoint_name);
592         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);
593         if(rcl == 0) {
594             log_error("could not created yang path\n");
595             return NTS_ERR_FAILED;
596         }
597
598         sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/map-type", endpoint_name);
599         rcl = lyd_new_path(netconf_node, session_context, xpath, "ietf-x509-cert-to-name:specified", 0, LYD_PATH_OPT_NOPARENTRET);
600         if(rcl == 0) {
601             log_error("could not created yang path\n");
602             return NTS_ERR_FAILED;
603         }
604
605         sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/name", endpoint_name);
606         rcl = lyd_new_path(netconf_node, 0, xpath, "netconf", 0, LYD_PATH_OPT_NOPARENTRET);
607         if(rcl == 0) {
608             log_error("could not created yang path\n");
609             return NTS_ERR_FAILED;
610         }
611     }
612
613     return NTS_ERR_OK;
614 }
615
616 static int configure_endpoints_connections(sr_session_ctx_t *session) {
617     assert(session);
618
619     int rc = NTS_ERR_OK;
620
621     struct lys_module *module = 0;
622     module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-netconf-server", 0, 0);
623     if(module == 0) {
624         log_error("could not get module %s from context\n", "ietf-netconf-server");
625         return NTS_ERR_FAILED;
626     }
627
628
629     struct lyd_node *netconf_node = 0;
630     netconf_node = lyd_new_path(NULL, session_context, "/ietf-netconf-server:netconf-server", 0, 0, 0);
631     if(netconf_node == 0) {
632         log_error("could not create a new lyd_node\n");
633         return NTS_ERR_FAILED;
634     }
635
636     // create the SSH endpoints in ietf-netconf-server
637     int ssh_connections = 0;
638     if(framework_arguments.nts_mode == NTS_MODE_MANAGER) {
639         ssh_connections = 1;
640     }
641     else {
642         ssh_connections = framework_environment.settings.ssh_connections;
643     }
644
645     if(ssh_connections == 0) {
646         log_error("ssh_connections must be at least 1\n");
647         return NTS_ERR_FAILED;
648     }
649
650     rc = create_ssh_listen_endpoints(netconf_node, ssh_connections);
651     if(rc != NTS_ERR_OK) {
652         log_error("could not create %d SSH Listen endpoints on the NETCONF Server\n", ssh_connections);
653         return NTS_ERR_FAILED;
654     }
655
656     // create the TLS endpoints in ietf-netconf-server
657     if(framework_arguments.nts_mode != NTS_MODE_MANAGER) {
658         rc = create_tls_listen_endpoints(netconf_node, framework_environment.settings.tls_connections);
659         if(rc != NTS_ERR_OK) {
660             log_error("could not create %d TLS Listen endpoints on the NETCONF Server\n", framework_environment.settings.tls_connections);
661             return NTS_ERR_FAILED;
662         }
663     }
664     
665     rc = sr_edit_batch(session, netconf_node, "replace");
666     if(rc != SR_ERR_OK) {
667         log_error("could not edit batch on datastore\n");
668         return NTS_ERR_FAILED;
669     }
670
671     rc = sr_validate(session, "ietf-netconf-server", 0);
672     if(rc != SR_ERR_OK) {
673         struct ly_err_item *err = ly_err_first(session_context);
674         log_error("sr_validate issues on STARTUP: %s\n", err->msg);
675         return NTS_ERR_FAILED;
676     }
677
678     rc = sr_apply_changes(session, 0, 0);
679     if(rc != SR_ERR_OK) {
680         log_error("could not apply changes on datastore\n");
681         return NTS_ERR_FAILED;
682     }
683     
684     return NTS_ERR_OK;
685 }