@@ -6307,4 +6307,121 @@ nc_server_config_oper_get_supported_tls_algs(const struct ly_ctx *ctx, struct ly
63076307 return nc_server_config_oper_get_algs (ctx , mod , NULL , nc_tls_supported_cipher_suites , supported_algs );
63086308}
63096309
6310+ API int
6311+ nc_server_config_oper_get_user_password_last_modified (const struct ly_ctx * ctx , const char * ch_client ,
6312+ const char * endpoint , const char * username , struct lyd_node * * last_modified )
6313+ {
6314+ int rc = 0 , r , locked = 0 ;
6315+ LY_ARRAY_COUNT_TYPE i ;
6316+ struct nc_server_ssh_opts * ssh_opts = NULL ;
6317+ struct nc_endpt * endpt = NULL ;
6318+ struct nc_ch_client * client = NULL ;
6319+ struct nc_ch_endpt * ch_endpt = NULL ;
6320+ time_t found_time = 0 ;
6321+ char * time_str = NULL , * path = NULL ;
6322+
6323+ NC_CHECK_ARG_RET (NULL , endpoint , username , last_modified , 1 );
6324+
6325+ * last_modified = NULL ;
6326+
6327+ /* LOCK */
6328+ pthread_rwlock_rdlock (& server_opts .config_lock );
6329+ locked = 1 ;
6330+
6331+ if (ch_client ) {
6332+ /* find the call-home client */
6333+ LY_ARRAY_FOR (server_opts .config .ch_clients , i ) {
6334+ if (!strcmp (server_opts .config .ch_clients [i ].name , ch_client )) {
6335+ client = & server_opts .config .ch_clients [i ];
6336+ break ;
6337+ }
6338+ }
6339+ if (!client ) {
6340+ ERR (NULL , "Call-home client '%s' not found." , ch_client );
6341+ rc = 1 ;
6342+ goto cleanup ;
6343+ }
6344+
6345+ /* find the endpoint */
6346+ LY_ARRAY_FOR (client -> ch_endpts , struct nc_ch_endpt , ch_endpt ) {
6347+ if (!strcmp (ch_endpt -> name , endpoint ) && (ch_endpt -> ti == NC_TI_SSH )) {
6348+ ssh_opts = ch_endpt -> opts .ssh ;
6349+ break ;
6350+ }
6351+ }
6352+
6353+ if (!ssh_opts ) {
6354+ ERR (NULL , "Endpoint '%s' with SSH transport not found in call-home client '%s'." , endpoint , ch_client );
6355+ rc = 1 ;
6356+ goto cleanup ;
6357+ }
6358+ } else {
6359+ /* no call-home client specified, search in listening endpoints */
6360+ LY_ARRAY_FOR (server_opts .config .endpts , struct nc_endpt , endpt ) {
6361+ if (!strcmp (endpt -> name , endpoint ) && (endpt -> ti == NC_TI_SSH )) {
6362+ ssh_opts = endpt -> opts .ssh ;
6363+ break ;
6364+ }
6365+ }
6366+
6367+ if (!ssh_opts ) {
6368+ ERR (NULL , "Endpoint '%s' with SSH transport not found in listening endpoints." , endpoint );
6369+ rc = 1 ;
6370+ goto cleanup ;
6371+ }
6372+ }
6373+
6374+ /* find the SSH user */
6375+ LY_ARRAY_FOR (ssh_opts -> auth_clients , i ) {
6376+ if (!strcmp (ssh_opts -> auth_clients [i ].username , username )) {
6377+ found_time = ssh_opts -> auth_clients [i ].password_last_modified ;
6378+ break ;
6379+ }
6380+ }
6381+ if (i == LY_ARRAY_COUNT (ssh_opts -> auth_clients )) {
6382+ ERR (NULL , "SSH user '%s' not found on endpoint '%s'." , username , endpoint );
6383+ rc = 1 ;
6384+ goto cleanup ;
6385+ }
6386+
6387+ /* UNLOCK */
6388+ pthread_rwlock_unlock (& server_opts .config_lock );
6389+ locked = 0 ;
6390+
6391+ if (!found_time ) {
6392+ /* password has never been modified */
6393+ goto cleanup ;
6394+ }
6395+
6396+ /* convert time to string */
6397+ NC_CHECK_ERR_GOTO (ly_time_time2str (found_time , NULL , & time_str ), rc = 1 , cleanup );
6398+
6399+ /* create the path to the oper data node */
6400+ if (ch_client ) {
6401+ r = asprintf (& path , "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='%s']/endpoints/"
6402+ "endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/users/user[name='%s']/password/"
6403+ "last-modified" , ch_client , endpoint , username );
6404+ } else {
6405+ r = asprintf (& path , "/ietf-netconf-server:netconf-server/listen/endpoints/endpoint[name='%s']/ssh/"
6406+ "ssh-server-parameters/client-authentication/users/user[name='%s']/password/last-modified" ,
6407+ endpoint , username );
6408+ }
6409+ if (r == -1 ) {
6410+ rc = 1 ;
6411+ ERRMEM ;
6412+ goto cleanup ;
6413+ }
6414+
6415+ /* create the operational data */
6416+ NC_CHECK_ERR_GOTO (lyd_new_path (NULL , ctx , path , time_str , 0 , last_modified ), rc = 1 , cleanup );
6417+ cleanup :
6418+ if (locked ) {
6419+ /* UNLOCK */
6420+ pthread_rwlock_unlock (& server_opts .config_lock );
6421+ }
6422+ free (time_str );
6423+ free (path );
6424+ return rc ;
6425+ }
6426+
63106427#endif /* NC_ENABLED_SSH_TLS */
0 commit comments