-
Notifications
You must be signed in to change notification settings - Fork 157
Expand file tree
/
Copy pathsession_p.h
More file actions
1580 lines (1342 loc) · 60.1 KB
/
session_p.h
File metadata and controls
1580 lines (1342 loc) · 60.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* @file session_p.h
* @author Radek Krejci <rkrejci@cesnet.cz>
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief libnetconf2 session manipulation
*
* @copyright
* Copyright (c) 2017 - 2025 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#ifndef NC_SESSION_PRIVATE_H_
#define NC_SESSION_PRIVATE_H_
#define _GNU_SOURCE
#include <poll.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/types.h>
#include <libyang/libyang.h>
#include "compat.h"
#include "config.h"
#include "session_client.h"
#include "session_server.h"
#include "session_server_ch.h"
#ifdef NC_ENABLED_SSH_TLS
#include "session_wrapper.h"
#endif /* NC_ENABLED_SSH_TLS */
extern struct nc_server_opts server_opts;
#define client_opts nc_client_context_location()->opts
#define client_unix_opts nc_client_context_location()->unix_opts
#define client_ssh_opts nc_client_context_location()->ssh_opts
#define client_ssh_ch_opts nc_client_context_location()->ssh_ch_opts
#define client_tls_opts nc_client_context_location()->tls_opts
#define client_tls_ch_opts nc_client_context_location()->tls_ch_opts
/**
* Size added to the reader buffer on realloc.
* Used only for NETCONF 1.0 messages (always the hello message).
*/
#define NC_READ_BUF_SIZE_STEP 512
/**
* Maximum size of a written framing message chunk (spec max is 2^32 - 1).
*/
#define NC_WRITE_CHUNK_SIZE_MAX 1024 * 10
/**
* Maximum size of a read framing message chunk.
*/
#define NC_READ_CHUNK_SIZE_MAX 1024 * 1024 * 10
/**
* Sleep time in usec to wait between nc_recv_notif() calls.
*/
#define NC_CLIENT_NOTIF_THREAD_SLEEP 10000
/**
* Timeout in msec for transport-related data to arrive (ssh_handle_key_exchange(), SSL_accept(), SSL_connect()).
* It can be quite a lot on slow machines (waiting for TLS cert-to-name resolution, ...).
*/
#define NC_TRANSPORT_TIMEOUT 10000
/**
* Timeout in msec for acquiring a lock of a session (used with a condition, so higher numbers could be required
* only in case of extreme concurrency).
*/
#define NC_SESSION_LOCK_TIMEOUT 500
/**
* Timeout in msec for acquiring a lock of a session that is supposed to be freed.
*/
#define NC_SESSION_FREE_LOCK_TIMEOUT 1000
/**
* Timeout in msec to poll for SSH channel EOF response when closing a session.
*/
#define NC_SESSION_FREE_SSH_POLL_EOF_TIMEOUT 100
/**
* Timeout in msec for a thread to wait for its turn to work with a pollsession structure.
*/
#define NC_PS_QUEUE_TIMEOUT 5000
/**
* @brief Maximum time (in seconds) to wait for a pending configuration
* update to complete before rejecting a new update request.
*/
#define NC_SERVER_CONFIG_UPDATE_WAIT_TIMEOUT_SEC 5
/**
* Time slept in msec if no endpoint was created for a running Call Home client.
*/
#define NC_CH_NO_ENDPT_WAIT 1000
/**
* Time slept in msec between Call Home thread session idle timeout checks.
*/
#define NC_CH_THREAD_IDLE_TIMEOUT_SLEEP 1000
/**
* Timeout in msec for a Call Home socket to establish its connection.
*/
#define NC_CH_CONNECT_TIMEOUT 500
/**
* @brief Timeout in msec for acquiring the hello_lock
* (iterating through all YANG modules + building capability strings)
*/
#define NC_HELLO_LOCK_TIMEOUT 5000
/**
* @brief Timeout in msec for acquiring the ch_threads_lock
* (simple array iteration and thread signaling operations)
*/
#define NC_CH_THREADS_LOCK_TIMEOUT 1000
/**
* @brief Timeout in msec for acquiring the Call Home thread cond_lock
* (short critical sections used to signal thread termination and gate condition waits)
*/
#define NC_CH_COND_LOCK_TIMEOUT 1000
/**
* @brief Timeout in msec for acquiring the certificate expiration notification lock
* (short critical sections for flag updates and condition signaling)
*/
#define NC_CERT_EXP_LOCK_TIMEOUT 1000
/**
* @brief Timeout in msec for acquiring the config_lock
* (socket binding and Call Home client dispatching can involve network operations)
*/
#define NC_CONFIG_LOCK_TIMEOUT 10000
/**
* @brief Timeout in msec for acquiring session's ch_lock
* (just simple session flag checks and updates)
*/
#define NC_SESSION_CH_LOCK_TIMEOUT 1000
/**
* @brief Timeout in msec for acquiring the pollsession's lock
* (only O(n) array manipulation, where n is number of sessions (small usually))
*/
#define NC_PS_LOCK_TIMEOUT 1000
/**
* @brief Timeout in msec for acquiring the notification status lock
* (short critical sections for incrementing/decrementing notification status)
*/
#define NC_SESSION_NTF_STATUS_LOCK_TIMEOUT 500
/**
* Number of sockets kept waiting to be accepted.
*/
#define NC_REVERSE_QUEUE 5
/**
* Time slept in msec in each cycle of the client monitoring thread.
*/
#define NC_CLIENT_MONITORING_BACKOFF 200
/**
* Timeout in msec for acquiring a lock of a client monitoring thread.
*/
#define NC_CLIENT_MONITORING_LOCK_TIMEOUT 500
/**
* TLS key log file environment variable name.
*/
#define NC_TLS_KEYLOGFILE_ENV "SSLKEYLOGFILE"
#define NC_VERSION_10_ENDTAG "]]>]]>"
#define NC_VERSION_10_ENDTAG_LEN 6
/**
* Enumeration of diff operation types.
*/
enum nc_operation {
NC_OP_UNKNOWN = 0,
NC_OP_NONE,
NC_OP_CREATE,
NC_OP_DELETE,
NC_OP_REPLACE
};
/**
* @brief Enumeration of rwlock mode.
*/
enum nc_rwlock_mode {
NC_RWLOCK_NONE = 0, /**< Lock not held */
NC_RWLOCK_READ, /**< Read lock mode */
NC_RWLOCK_WRITE /**< Write lock mode */
};
/**
* Enumeration of key or certificate store type.
*/
enum nc_store_type {
NC_STORE_UNKNOWN = 0, /**< unknown store type */
NC_STORE_LOCAL, /**< key/certificate is stored locally in the ietf-netconf-server YANG data */
NC_STORE_KEYSTORE, /**< key/certificate is stored externally in a keystore module YANG data */
NC_STORE_TRUSTSTORE, /**< key/certificate is stored externally in a truststore module YANG data */
NC_STORE_SYSTEM /**< key/certificate is managed by the system */
};
#ifdef NC_ENABLED_SSH_TLS
#include <curl/curl.h>
#include <libssh/libssh.h>
/**
* Timeout set for libssh (s).
*/
#define NC_SSH_TIMEOUT 10
/**
* @brief Enumeration of SSH public key formats.
*/
enum nc_pubkey_format {
NC_PUBKEY_FORMAT_UNKNOWN = 0, /**< Unknown format */
NC_PUBKEY_FORMAT_SSH, /**< see RFC 4253, section 6.6 */
NC_PUBKEY_FORMAT_X509 /**< see RFC 5280 sec. 4.1.2.7 */
};
/**
* @brief Enumeration of private key file formats.
*/
enum nc_privkey_format {
NC_PRIVKEY_FORMAT_UNKNOWN = 0, /**< Unknown format */
NC_PRIVKEY_FORMAT_RSA, /**< PKCS1 RSA format */
NC_PRIVKEY_FORMAT_EC, /**< SEC1 EC format */
NC_PRIVKEY_FORMAT_X509, /**< X509 (PKCS8) format */
NC_PRIVKEY_FORMAT_OPENSSH /**< OpenSSH format */
};
/**
* @brief Enumeration of SSH keyboard-interactive authentication methods.
*/
enum nc_kbdint_auth_method {
NC_KBDINT_AUTH_METHOD_NONE = 0, /**< Keyboard-interactive authentication disabled. */
NC_KBDINT_AUTH_METHOD_SYSTEM /**< Keyboard-interactive authentication is left to the system (PAM, shadow, etc.). */
};
/**
* @brief Certificate representation.
*/
struct nc_certificate {
char *name; /**< Optional identifier of the certificate. */
char *data; /**< Base-64 encoded certificate. */
};
/**
* @brief Public key representation.
*/
struct nc_public_key {
char *name; /**< Optional identifier of the public key. */
enum nc_pubkey_format type; /**< Type of the public key. */
char *data; /**< Base-64 encoded public key. */
};
/**
* @brief Private key representation.
*/
struct nc_private_key {
enum nc_privkey_format type; /**< Type of the private key. */
char *data; /**< Base-64 encoded private key. */
};
/**
* @brief Asymmetric key pair representation.
*/
struct nc_asymmetric_key {
char *name; /**< Optional identifier of the key pair. */
struct nc_public_key pubkey; /**< Public key. */
struct nc_private_key privkey; /**< Private key. */
};
/**
* @brief Store of trusted certificates and public keys.
*/
struct nc_truststore {
/**
* @brief Bag of certificates that should share the same purpose.
*/
struct nc_certificate_bag {
char *name; /**< Identifier of the certificate bag. */
char *description; /**< Optional description of the certificate bag. */
struct nc_certificate *certs; /**< Certificates in the bag (sized-array, see libyang docs). */
} *cert_bags; /**< Certificate bags (sized-array, see libyang docs). */
/**
* @brief Bag of public keys that should share the same purpose.
*/
struct nc_public_key_bag {
char *name; /**< Identifier of the public key bag. */
char *description; /**< Optional description of the public key bag. */
struct nc_public_key *pubkeys; /**< Public keys in the bag (sized-array, see libyang docs). */
} *pubkey_bags; /**< Public key bags (sized-array, see libyang docs). */
};
/**
* @brief Keystore YANG module representation.
*/
struct nc_keystore {
struct nc_keystore_entry {
struct nc_asymmetric_key asym_key; /**< Stored asymmetric key. */
struct nc_certificate *certs; /**< Certificates associated with the asymmetric key (sized-array, see libyang docs). */
} *entries; /**< Asymmetric key + certs entries (sized-array, see libyang docs). */
};
/**
* @brief Tracks the state of a client's authentication.
*/
struct nc_auth_state {
int methods; /**< Bit field of authentication methods that the user supports. */
int method_count; /**< Number of authentication methods that the user supports. */
int success_methods; /**< Bit field of authentication methods that the user successfully authenticated with. */
int success_count; /**< Number of authentication methods that the user successfully authenticated with. */
};
/**
* @brief Client authorized to connect to the server over SSH.
*/
struct nc_auth_client {
char *username; /**< Identifier of the client. */
enum nc_store_type pubkey_store; /**< Specifies how/where the client's public keys are stored. */
union {
struct nc_public_key *pubkeys; /**< Locally-defined public keys (sized-array, see libyang docs). */
char *ts_ref; /**< Name of the referenced truststore public key bag. */
};
char *password; /**< Password for password authentication. */
time_t password_last_modified; /**< Time of the last password modification. */
enum nc_kbdint_auth_method kbdint_method; /**< Keyboard-interactive authentication method,
* may be extended by e.g. a union for each method when needed. */
int none_enabled; /**< Whether "none" authentication is enabled for this user. */
};
/**
* @brief Server's SSH host key.
*/
struct nc_hostkey {
char *name; /**< Identifier of the hostkey. */
enum nc_store_type store; /**< Specifies how/where the key is stored. */
union {
struct nc_asymmetric_key key; /**< Locally-defined key. */
char *ks_ref; /**< Name of the referenced keystore key. */
};
};
/**
* @brief Server options for configuring the SSH transport protocol.
*/
struct nc_server_ssh_opts {
struct nc_hostkey *hostkeys; /**< Server's hostkeys (sized-array, see libyang docs). */
struct nc_auth_client *auth_clients; /**< Server's authorized clients (sized-array, see libyang docs). */
char *referenced_endpt_name; /**< Reference to another endpoint (used for client authentication). */
char *hostkey_algs; /**< Used hostkey algorithms (comma-separated list). */
char *encryption_algs; /**< Used encryption algorithms (comma-separated list). */
char *kex_algs; /**< Used key exchange algorithms (comma-separated list). */
char *mac_algs; /**< Used MAC algorithms (comma-separated list). */
char *banner; /**< SSH banner message, sent before authentication. */
uint16_t auth_timeout; /**< Authentication timeout. */
};
/**
* @brief Storing downloaded data via CURL.
*/
struct nc_curl_data {
unsigned char *data; /**< Downloaded data */
size_t size; /**< Size of downloaded data */
};
/**
* @brief Cert-to-name entries.
*/
struct nc_ctn {
uint32_t id; /**< ID of the entry, the lower the higher priority */
char *fingerprint; /**< Fingerprint of the entry */
NC_TLS_CTN_MAPTYPE map_type; /**< Specifies how to get the username from the certificate */
char *name; /**< Username for this entry */
struct nc_ctn *next; /**< Linked-list reference to the next entry */
};
/**
* @brief Enumeration of supported TLS versions.
*/
enum nc_tls_version {
NC_TLS_VERSION_NONE = 0, /**< Unknown TLS version */
NC_TLS_VERSION_1_2, /**< TLS version 1.2 */
NC_TLS_VERSION_1_3 /**< TLS version 1.3 */
};
/**
* @brief Server's TLS client authentication configuration.
*/
struct nc_server_tls_client_auth {
enum nc_store_type ca_certs_store; /**< Specifies how/where the CA certificates are stored. */
union {
struct nc_certificate *ca_certs; /**< Locally-defined CA certificates (sized-array, see libyang docs). */
char *ca_cert_bag_ts_ref; /**< Name of the referenced truststore certificate bag. */
};
enum nc_store_type ee_certs_store; /**< Specifies how/where the end-entity certificates are stored. */
union {
struct nc_certificate *ee_certs; /**< Locally-defined end-entity certificates (sized-array, see libyang docs). */
char *ee_cert_bag_ts_ref; /**< Name of the referenced truststore certificate bag. */
};
};
/**
* @brief Server options for configuring the TLS transport protocol.
*/
struct nc_server_tls_opts {
enum nc_store_type cert_store; /**< Specifies how/where the server's key and certificate are stored. */
union {
struct {
struct nc_asymmetric_key key; /**< Locally-defined key. */
struct nc_certificate cert; /**< Locally-defined certificate. */
} local; /**< Local definition of the server's key and certificate. */
struct {
char *asym_key_ref; /**< Name of the referenced keystore asymmetric key. */
char *cert_ref; /**< Name of the referenced keystore certificate. */
} keystore; /**< Keystore reference of the server's key and certificate. */
};
struct nc_server_tls_client_auth client_auth; /**< Client authentication configuration. */
struct nc_ctn *ctn; /**< Cert-to-name entries linked list */
char *referenced_endpt_name; /**< Reference to another endpoint (used for client authentication). */
enum nc_tls_version min_version; /**< Minimum supported TLS version. */
enum nc_tls_version max_version; /**< Maximum supported TLS version. */
char *cipher_suites; /**< Allowed cipher suites (colon-separated list). */
};
#endif /* NC_ENABLED_SSH_TLS */
/**
* @brief TCP keepalives configuration.
*/
struct nc_keepalives {
int enabled; /**< Indicates that keepalives are enabled. */
uint16_t idle_time; /**< Idle timeout. */
uint16_t max_probes; /**< Maximum number of probes. */
uint16_t probe_interval; /**< Probe interval. */
};
/**
* @brief Enumeration of UNIX socket path types.
*/
enum nc_unix_socket_path_type {
NC_UNIX_SOCKET_PATH_UNKNOWN = 0, /**< Unknown or uninitialized path type. */
NC_UNIX_SOCKET_PATH_HIDDEN, /**< Socket path is hidden from YANG; configured via API. */
NC_UNIX_SOCKET_PATH_FILE /**< Socket path is explicitly configured in YANG. */
};
/**
* @brief Server options for configuring the UNIX transport protocol.
*/
struct nc_server_unix_opts {
enum nc_unix_socket_path_type path_type; /**< Method used to determine the socket path. */
mode_t mode; /**< Socket file permissions (defaults to rw-rw----). */
uid_t uid; /**< Owner of the socket file. */
gid_t gid; /**< Group owner of the socket file. */
struct nc_server_unix_user_mapping {
char *system_user; /**< System username for authentication. */
char **allowed_users; /**< Permitted NETCONF usernames (sized-array, see libyang docs). */
} *user_mappings; /**< Username mappings for the UNIX socket connection (sized-array, see libyang docs). */
};
/**
* @brief Stores information about a server endpoint binding.
*/
struct nc_bind {
char *address; /**< Either IPv4/IPv6 address or path to UNIX socket. */
uint16_t port; /**< Either port number or 0 for UNIX socket. */
int sock; /**< Socket file descriptor, -1 if not created yet. */
};
struct nc_client_unix_opts {
char *username;
};
#ifdef NC_ENABLED_SSH_TLS
/* number of all supported authentication methods */
#define NC_SSH_AUTH_COUNT 3
struct nc_client_ssh_opts {
char *knownhosts_path; /**< path to known_hosts file */
NC_SSH_KNOWNHOSTS_MODE knownhosts_mode; /**< implies whether to check known_hosts or not */
/* SSH authentication method preferences */
struct {
NC_SSH_AUTH_TYPE type;
int16_t value;
} auth_pref[NC_SSH_AUTH_COUNT];
/* SSH key pairs */
struct {
char *pubkey_path;
char *privkey_path;
int8_t privkey_crypt;
} *keys;
uint16_t key_count;
/* SSH authentication callbacks */
char *(*auth_password)(const char *, const char *, void *);
char *(*auth_interactive)(const char *, const char *, const char *, int, void *);
char *(*auth_privkey_passphrase)(const char *, void *);
/* private data for the callbacks */
void *auth_password_priv;
void *auth_interactive_priv;
void *auth_privkey_passphrase_priv;
char *username;
};
struct nc_client_tls_opts {
char *cert_path;
char *key_path;
char *ca_file;
char *ca_dir;
};
#endif /* NC_ENABLED_SSH_TLS */
/**
* @brief Stores data for the client monitoring thread.
*/
struct nc_client_monitoring_thread_arg {
struct nc_session **sessions; /**< Array of monitored sessions. */
uint16_t session_count; /**< Number of monitored sessions. */
struct pollfd *pfds; /**< Array of poll file descriptors corresponding to the monitored sessions. */
nfds_t pfd_count; /**< Number of poll file descriptors. */
pthread_t tid; /**< Thread ID of the monitoring thread. */
int thread_running; /**< Flag representing the runningness of the monitoring thread. */
pthread_mutex_t lock; /**< Monitoring thread data lock. */
nc_client_monitoring_clb clb; /**< Callback called when a monitored session is terminated by the server. */
void *clb_data; /**< Data passed to the callback. */
void (*clb_free_data)(void *); /**< Callback to free the user data. */
};
/* ACCESS unlocked */
struct nc_client_opts {
char *schema_searchpath;
int auto_context_fill_disabled;
ly_module_imp_clb schema_clb;
void *schema_clb_data;
struct nc_keepalives ka;
char **capabilities; /**< Array of custom client capabilities. */
uint32_t capabilities_count; /**< Count of capabilities. */
struct nc_bind *ch_binds;
struct {
NC_TRANSPORT_IMPL ti;
char *hostname;
} *ch_binds_aux;
uint16_t ch_bind_count;
struct nc_client_monitoring_thread_arg monitoring_thread_data; /**< Data of the monitoring thread. */
};
/* ACCESS unlocked */
struct nc_client_context {
unsigned int refcount;
struct nc_client_opts opts;
struct nc_client_unix_opts unix_opts;
#ifdef NC_ENABLED_SSH_TLS
struct nc_client_ssh_opts ssh_opts;
struct nc_client_ssh_opts ssh_ch_opts;
struct nc_client_tls_opts tls_opts;
struct nc_client_tls_opts tls_ch_opts;
#endif /* NC_ENABLED_SSH_TLS */
};
#ifdef NC_ENABLED_SSH_TLS
/**
* @brief Stores time information used for creating certificate expiration intervals.
*/
struct nc_cert_exp_time {
int months;
int weeks;
int days;
int hours;
};
/**
* @brief Stores information about a certificate expiration notification.
*/
struct nc_cert_expiration {
time_t *starts_of_intervals; /**< Array of the starting times of the certificate expiration notification intervals. */
int current_interval; /**< Index of the current interval. */
time_t expiration_time; /**< Time of the certificate expiration. */
time_t notif_time; /**< Time of the next notification. */
char *xpath; /**< XPath to the certificate. */
};
/**
* @brief Certificate expiration notification thread data.
*/
struct nc_cert_exp_notif_thread_arg {
nc_cert_exp_notif_clb clb; /**< Callback called when a certificate expiration notification is ready to be sent. */
void *clb_data; /**< Data passed to the callback. */
void (*clb_free_data)(void *); /**< Callback to free the user data. */
};
/**
* @brief Auxiliary structure used for creating the XPaths to the certificates.
*/
struct nc_cert_path_aux {
const char *ch_client_name;
const char *endpt_name;
const char *ca_cert_name;
const char *ee_cert_name;
const char *ks_askey_name;
const char *ks_cert_name;
const char *ts_cbag_name;
const char *ts_cert_name;
};
/**
* @brief Update the values of the nc_cert_path_aux members.
*/
#define NC_CERT_EXP_UPDATE_CERT_PATH(cp, ch_client, endpt, ca_cert, \
ee_cert, ks_askey, ks_cert, ts_cbag, ts_cert) \
(cp)->ch_client_name = (ch_client); \
(cp)->endpt_name = (endpt); \
(cp)->ca_cert_name = (ca_cert); \
(cp)->ee_cert_name = (ee_cert); \
(cp)->ks_askey_name = (ks_askey); \
(cp)->ks_cert_name = (ks_cert); \
(cp)->ts_cbag_name = (ts_cbag); \
(cp)->ts_cert_name = (ts_cert)
#endif /* NC_ENABLED_SSH_TLS */
/**
* @brief Call Home client thread data.
*/
struct nc_server_ch_thread_arg {
char *client_name;
const struct ly_ctx *(*acquire_ctx_cb)(void *cb_data); /**< acquiring libyang context cb */
void (*release_ctx_cb)(void *cb_data); /**< releasing libyang context cb */
void *ctx_cb_data; /**< acq/rel cb data */
int (*new_session_cb)(const char *client_name, struct nc_session *new_session, void *user_data); /**< creating new session cb */
void *new_session_cb_data; /**< new session cb data */
void (*new_session_fail_cb)(const char *client_name, const char *endpt_name, uint8_t max_attempts,
uint8_t cur_attempt, void *user_data); /**< failed to create a new session cb */
void *new_session_fail_cb_data; /**< new session fail cb data */
pthread_t tid; /**< Thread ID of the Call Home client thread. */
ATOMIC_T thread_running; /**< Non-zero while the Call Home thread is running. Atomic for lock-free checks,
but also used with the condition variable under cond_lock for signalling. */
pthread_mutex_t cond_lock; /**< Condition's lock used for signalling the thread to terminate */
pthread_cond_t cond; /**< Condition used for signalling the thread to terminate */
};
struct nc_server_config {
uint16_t idle_timeout; /**< Idle timeout of the server sessions. */
char **ignored_modules; /**< Names of YANG modules that are not reported in the server <hello> message (sized-array, see libyang docs). */
struct nc_endpt {
char *name; /**< Identifier of the endpoint. */
struct nc_bind *binds; /**< Listening binds of the endpoint (sized-array, see libyang docs). */
struct nc_keepalives ka; /**< TCP keepalives configuration. */
NC_TRANSPORT_IMPL ti; /**< Transport implementation of the endpoint. */
union {
#ifdef NC_ENABLED_SSH_TLS
struct nc_server_ssh_opts *ssh; /**< SSH transport options. */
struct nc_server_tls_opts *tls; /**< TLS transport options. */
#endif /* NC_ENABLED_SSH_TLS */
struct nc_server_unix_opts *unix; /**< UNIX socket transport options. */
} opts;
} *endpts; /**< Listening endpoints (sized-array, see libyang docs). */
struct nc_ch_client {
char *name; /**< Identifier of the Call Home client. */
struct nc_ch_endpt {
char *name; /**< Identifier of the Call Home endpoint. */
char *src_addr; /**< IP address to bind to when connecting to a Call Home client. */
uint16_t src_port; /**< Port to bind to when connecting to a Call Home client. */
char *dst_addr; /**< IP address of the Call Home client. */
uint16_t dst_port; /**< Port of the Call Home client. */
int sock_pending; /**< Socket file descriptor of the pending connection to the Call Home client. */
struct nc_keepalives ka; /**< Keepalives configuration data for the Call Home endpoint. */
NC_TRANSPORT_IMPL ti; /**< Transport implementation of the Call Home endpoint. */
union {
#ifdef NC_ENABLED_SSH_TLS
struct nc_server_ssh_opts *ssh; /**< SSH transport options for the Call Home endpoint. */
struct nc_server_tls_opts *tls; /**< TLS transport options for the Call Home endpoint. */
#endif /* NC_ENABLED_SSH_TLS */
} opts;
} *ch_endpts; /**< Call Home endpoints (sized-array, see libyang docs). */
NC_CH_CONN_TYPE conn_type; /**< Type of the Call Home connection. */
struct {
uint16_t period; /**< Period of a periodic Call Home connection in seconds. */
time_t anchor_time; /**< Anchor time of a periodic Call Home connection. */
uint16_t idle_timeout; /**< Idle timeout of a periodic Call Home connection in seconds. */
};
NC_CH_START_WITH start_with; /**< How to select the Call Home endpoint to connect to. */
uint8_t max_attempts; /**< Maximum number of attempts to connect to the given Call Home endpoint. */
uint16_t max_wait; /**< Maximum time to wait for a Call Home connection in seconds. */
struct nc_server_ch_thread_arg *thread; /**< Call Home client thread data, if dispatched. */
} *ch_clients; /**< Call Home clients (sized-array, see libyang docs). */
#ifdef NC_ENABLED_SSH_TLS
struct nc_keystore keystore; /**< Asymmetric and symmetric key storage used for server identity. */
struct nc_truststore truststore; /**< Public keys and certificates storage used for client authentication. */
/**
* @brief Time intervals for certificate expiration notifications.
*
* See libnetconf2-netconf-server YANG module for more details.
*/
struct nc_cert_exp_time_interval {
struct nc_cert_exp_time anchor; /**< Lower bound of the given interval. */
struct nc_cert_exp_time period; /**< Period of the given interval. */
} *cert_exp_notif_intervals; /**< Certificate expiration notification intervals (sized-array, see libyang docs). */
#endif /* NC_ENABLED_SSH_TLS */
};
struct nc_server_opts {
/* ACCESS locked - hello lock - separate lock to not always hold config_lock */
pthread_rwlock_t hello_lock; /**< Needs to be held while the server <hello> message is being generated. */
NC_WD_MODE wd_basic_mode; /**< With-defaults basic mode of the server. */
int wd_also_supported; /**< Bitmap of with-defaults modes that are also supported by the server. */
char **capabilities; /**< Array of server's capabilities. */
uint32_t capabilities_count; /**< Number of server's capabilities. */
char *(*content_id_clb)(void *user_data); /**< Callback for generating content_id for ietf-yang-library data. */
void *content_id_data; /**< Data passed to the content_id_clb callback. */
void (*content_id_data_free)(void *data); /**< Callback to free the content_id_data. */
/* ACCESS locked - options modified by YANG data/API - WRITE lock
* - options read when accepting sessions - READ lock */
pthread_rwlock_t config_lock; /**< Lock for the server configuration. */
struct nc_server_config config; /**< YANG Server configuration. */
#ifdef NC_ENABLED_SSH_TLS
char *authkey_path_fmt; /**< Path to users' public keys that may contain tokens with special meaning. */
char *pam_config_name; /**< PAM configuration file name. */
char *ssh_protocol_string; /**< SSH protocol identification string. */
int (*interactive_auth_clb)(const struct nc_session *session, ssh_session ssh_sess, ssh_message msg, void *user_data);
void *interactive_auth_data;
void (*interactive_auth_data_free)(void *data);
int (*user_verify_clb)(const struct nc_session *session);
/**
* @brief Data for automatically dispatching Call Home clients.
*/
struct {
nc_server_ch_session_acquire_ctx_cb acquire_ctx_cb; /**< Acquiring libyang context callback. */
nc_server_ch_session_release_ctx_cb release_ctx_cb; /**< Releasing libyang context callback. */
void *ctx_cb_data; /**< Data passed to the callbacks above. */
nc_server_ch_new_session_cb new_session_cb; /**< New session callback. */
void *new_session_cb_data; /**< Data passed to the new_session_cb callback. */
nc_server_ch_new_session_fail_cb new_session_fail_cb; /**< New session fail callback, */
void *new_session_fail_cb_data; /**< Data passed to the new_session_fail_cb callback. */
} ch_dispatch_data;
struct {
pthread_t tid; /**< Thread ID of the certificate expiration notification thread. */
int thread_running; /**< Flag representing the runningness of the cert exp notification thread. */
pthread_mutex_t lock; /**< Certificate expiration notification thread's data and cond lock. */
pthread_cond_t cond; /**< Condition for the certificate expiration notification thread. */
} cert_exp_notif;
#endif /* NC_ENABLED_SSH_TLS */
/**
* @brief Entry for a UNIX socket path configured via API (Hidden).
*
* These paths are not part of the YANG configuration and are managed manually by the application.
*/
struct nc_server_unix_path_entry {
char *endpt_name; /**< Name of the endpoint using this path. */
char *path; /**< The actual filesystem path for the socket. */
} *unix_paths; /**< Array of UNIX socket paths set via API (sized-array, see libyang docs). */
char *unix_socket_dir; /**< Base directory for UNIX sockets created by the server. */
/* ACCESS unlocked */
ATOMIC_T new_session_id;
#ifdef NC_ENABLED_SSH_TLS
/* ACCESS unlocked - set from env */
FILE *tls_keylog_file; /**< File to log TLS secrets to. */
#endif
/* ACCESS locked - separate lock to allow concurrent reads of the config while an update is being applied */
pthread_mutex_t config_update_lock; /**< Lock for synchronizing configuration updates, used to wait for pending
configuration update to complete before accepting a new one. */
};
/**
* @brief Type of the session
*/
typedef enum {
NC_CLIENT, /**< client side */
NC_SERVER /**< server side */
} NC_SIDE;
/**
* @brief Container to serialize RPC messages
*/
struct nc_msg_cont {
struct ly_in *msg;
NC_MSG_TYPE type; /**< can be either NC_MSG_REPLY or NC_MSG_NOTIF */
struct nc_msg_cont *next;
};
/**
* @brief NETCONF session structure
*/
struct nc_session {
NC_STATUS status; /**< status of the session */
NC_SESSION_TERM_REASON term_reason; /**< reason of termination, if status is NC_STATUS_INVALID */
uint32_t killed_by; /**< session responsible for termination, if term_reason is NC_SESSION_TERM_KILLED */
NC_SIDE side; /**< side of the session: client or server */
/* NETCONF data */
uint32_t id; /**< NETCONF session ID (session-id-type) */
NC_PROT_VERSION version; /**< NETCONF protocol version */
char **cpblts; /**< NETCONF capabilities received from the other end */
/* Transport implementation */
NC_TRANSPORT_IMPL ti_type; /**< transport implementation type to select items from ti union */
pthread_mutex_t *io_lock; /**< input/output lock, note that in case of libssh TI, it will be shared with
other NETCONF sessions on the same SSH session (but different SSH channel) */
union {
struct {
int in; /**< input file descriptor */
int out; /**< output file descriptor */
} fd; /**< NC_TI_FD transport implementation structure */
struct {
int sock; /**< socket file descriptor */
} unixsock; /**< NC_TI_UNIX transport implementation structure */
#ifdef NC_ENABLED_SSH_TLS
struct {
ssh_channel channel;
ssh_session session;
struct nc_session *next; /**< pointer to the next NETCONF session on the same
SSH session, but different SSH channel. If no such session exists, it is NULL.
otherwise there is a ring list of the NETCONF sessions */
} libssh;
struct {
void *session;
void *config;
struct nc_tls_ctx ctx;
} tls;
#endif /* NC_ENABLED_SSH_TLS */
} ti; /**< transport implementation data */
char *username;
char *host;
uint16_t port;
char *path; /**< socket path in case of unix socket */
/* other */
struct ly_ctx *ctx; /**< libyang context of the session */
void *data; /**< arbitrary user data */
uint8_t flags; /**< various flags of the session */
/* shared flags */
#define NC_SESSION_SHAREDCTX 0x01 /**< context is shared */
#define NC_SESSION_CALLHOME 0x02 /**< session is Call Home and ch_lock is initialized */
#define NC_SESSION_CH_THREAD 0x04 /**< protected by ch_lock */
/* client flags */
#define NC_SESSION_CLIENT_NOT_STRICT 0x08 /**< some server modules failed to load so the data from
them will be ignored - not use strict flag for parsing */
#define NC_SESSION_CLIENT_MONITORED 0x40 /**< session is being monitored by the client monitoring thread */
/* server flags */
#ifdef NC_ENABLED_SSH_TLS
#define NC_SESSION_SSH_AUTHENTICATED 0x10 /**< SSH session authenticated */
#define NC_SESSION_SSH_SUBSYS_NETCONF 0x20 /**< netconf subsystem requested */
#endif
union {
struct {
/* client side only data */
uint64_t msgid;
pthread_mutex_t msgs_lock; /**< lock for the msgs buffer */
struct nc_msg_cont *msgs; /**< queue for messages received of different type than expected */
ATOMIC_T ntf_thread_count; /**< number of running notification threads */
ATOMIC_T ntf_thread_running; /**< flag whether there are notification threads for this session running or not */
} client;
struct {
/* server side only data */
struct timespec session_start; /**< real time the session was created */
time_t last_rpc; /**< monotonic time (seconds) the last RPC was received on this session */
pthread_mutex_t ntf_status_lock; /**< lock for ntf_status */
uint32_t ntf_status; /**< flag (count) whether the session is subscribed to notifications */
pthread_mutex_t rpc_lock; /**< lock indicating RPC processing, this lock is always locked before io_lock!! */
pthread_cond_t rpc_cond; /**< RPC condition (tied with rpc_lock and rpc_inuse) */
int rpc_inuse; /**< variable indicating whether there is RPC being processed or not (tied with
rpc_cond and rpc_lock) */
pthread_mutex_t ch_lock; /**< Call Home thread lock */
pthread_cond_t ch_cond; /**< Call Home thread condition */
#ifdef NC_ENABLED_SSH_TLS
uint16_t ssh_auth_attempts; /**< number of failed SSH authentication attempts */
void *client_cert; /**< TLS client certificate if used for authentication */
#endif /* NC_ENABLED_SSH_TLS */
} server;
} opts;
};
enum nc_ps_session_state {
NC_PS_STATE_NONE = 0, /**< session is not being worked with */
NC_PS_STATE_BUSY, /**< session is being polled or communicated on (and locked) */
NC_PS_STATE_INVALID /**< session is invalid and was already returned by another poll */
};
struct nc_ps_session {
struct nc_session *session;
enum nc_ps_session_state state;
};
/* ACCESS locked */
struct nc_pollsession {
struct nc_ps_session **sessions;
uint16_t session_count;
uint16_t last_event_session;
pthread_cond_t cond;
pthread_mutex_t lock;
uint8_t queue[NC_PS_QUEUE_SIZE]; /**< round buffer, queue is empty when queue_len == 0 */
uint8_t queue_begin; /**< queue starts on queue[queue_begin] */
uint8_t queue_len; /**< queue ends on queue[(queue_begin + queue_len - 1) % NC_PS_QUEUE_SIZE] */
};
struct nc_ntf_thread_arg {
struct nc_session *session;
nc_notif_dispatch_clb notif_clb;
void *user_data;
void (*free_data)(void *);
};