@@ -6333,4 +6333,121 @@ nc_server_config_oper_get_supported_tls_algs(const struct ly_ctx *ctx, struct ly
63336333 return nc_server_config_oper_get_algs (ctx , mod , NULL , nc_tls_supported_cipher_suites , supported_algs );
63346334}
63356335
6336+ API int
6337+ nc_server_config_oper_get_user_password_last_modified (const struct ly_ctx * ctx , const char * ch_client ,
6338+ const char * endpoint , const char * username , struct lyd_node * * last_modified )
6339+ {
6340+ int rc = 0 , r , locked = 0 ;
6341+ LY_ARRAY_COUNT_TYPE i ;
6342+ struct nc_server_ssh_opts * ssh_opts = NULL ;
6343+ struct nc_endpt * endpt = NULL ;
6344+ struct nc_ch_client * client = NULL ;
6345+ struct nc_ch_endpt * ch_endpt = NULL ;
6346+ time_t found_time = 0 ;
6347+ char * time_str = NULL , * path = NULL ;
6348+
6349+ NC_CHECK_ARG_RET (NULL , endpoint , username , last_modified , 1 );
6350+
6351+ * last_modified = NULL ;
6352+
6353+ /* LOCK */
6354+ pthread_rwlock_rdlock (& server_opts .config_lock );
6355+ locked = 1 ;
6356+
6357+ if (ch_client ) {
6358+ /* find the call-home client */
6359+ LY_ARRAY_FOR (server_opts .config .ch_clients , i ) {
6360+ if (!strcmp (server_opts .config .ch_clients [i ].name , ch_client )) {
6361+ client = & server_opts .config .ch_clients [i ];
6362+ break ;
6363+ }
6364+ }
6365+ if (!client ) {
6366+ ERR (NULL , "Call-home client '%s' not found." , ch_client );
6367+ rc = 1 ;
6368+ goto cleanup ;
6369+ }
6370+
6371+ /* find the endpoint */
6372+ LY_ARRAY_FOR (client -> ch_endpts , struct nc_ch_endpt , ch_endpt ) {
6373+ if (!strcmp (ch_endpt -> name , endpoint ) && (ch_endpt -> ti == NC_TI_SSH )) {
6374+ ssh_opts = ch_endpt -> opts .ssh ;
6375+ break ;
6376+ }
6377+ }
6378+
6379+ if (!ssh_opts ) {
6380+ ERR (NULL , "Endpoint '%s' with SSH transport not found in call-home client '%s'." , endpoint , ch_client );
6381+ rc = 1 ;
6382+ goto cleanup ;
6383+ }
6384+ } else {
6385+ /* no call-home client specified, search in listening endpoints */
6386+ LY_ARRAY_FOR (server_opts .config .endpts , struct nc_endpt , endpt ) {
6387+ if (!strcmp (endpt -> name , endpoint ) && (endpt -> ti == NC_TI_SSH )) {
6388+ ssh_opts = endpt -> opts .ssh ;
6389+ break ;
6390+ }
6391+ }
6392+
6393+ if (!ssh_opts ) {
6394+ ERR (NULL , "Endpoint '%s' with SSH transport not found in listening endpoints." , endpoint );
6395+ rc = 1 ;
6396+ goto cleanup ;
6397+ }
6398+ }
6399+
6400+ /* find the SSH user */
6401+ LY_ARRAY_FOR (ssh_opts -> auth_clients , i ) {
6402+ if (!strcmp (ssh_opts -> auth_clients [i ].username , username )) {
6403+ found_time = ssh_opts -> auth_clients [i ].password_last_modified ;
6404+ break ;
6405+ }
6406+ }
6407+ if (i == LY_ARRAY_COUNT (ssh_opts -> auth_clients )) {
6408+ ERR (NULL , "SSH user '%s' not found on endpoint '%s'." , username , endpoint );
6409+ rc = 1 ;
6410+ goto cleanup ;
6411+ }
6412+
6413+ /* UNLOCK */
6414+ pthread_rwlock_unlock (& server_opts .config_lock );
6415+ locked = 0 ;
6416+
6417+ if (!found_time ) {
6418+ /* password has never been modified */
6419+ goto cleanup ;
6420+ }
6421+
6422+ /* convert time to string */
6423+ NC_CHECK_ERR_GOTO (ly_time_time2str (found_time , NULL , & time_str ), rc = 1 , cleanup );
6424+
6425+ /* create the path to the oper data node */
6426+ if (ch_client ) {
6427+ r = asprintf (& path , "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='%s']/endpoints/"
6428+ "endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/users/user[name='%s']/password/"
6429+ "last-modified" , ch_client , endpoint , username );
6430+ } else {
6431+ r = asprintf (& path , "/ietf-netconf-server:netconf-server/listen/endpoints/endpoint[name='%s']/ssh/"
6432+ "ssh-server-parameters/client-authentication/users/user[name='%s']/password/last-modified" ,
6433+ endpoint , username );
6434+ }
6435+ if (r == -1 ) {
6436+ rc = 1 ;
6437+ ERRMEM ;
6438+ goto cleanup ;
6439+ }
6440+
6441+ /* create the operational data */
6442+ NC_CHECK_ERR_GOTO (lyd_new_path (NULL , ctx , path , time_str , 0 , last_modified ), rc = 1 , cleanup );
6443+ cleanup :
6444+ if (locked ) {
6445+ /* UNLOCK */
6446+ pthread_rwlock_unlock (& server_opts .config_lock );
6447+ }
6448+ free (time_str );
6449+ free (path );
6450+ return rc ;
6451+ }
6452+
63366453#endif /* NC_ENABLED_SSH_TLS */
0 commit comments