@@ -292,6 +292,115 @@ static void authconf_err(const char *errmsg)
292292 upslogx (LOG_ERR , "Error in parseconf(authconf): %s" , errmsg );
293293}
294294
295+ int upscli_normalize_auth_section_parts (
296+ char * * out_normalized_sect_name ,
297+ char * * p_sect_user ,
298+ int * out_fixed_sect_user ,
299+ char * * p_sect_host ,
300+ char * * p_sect_port )
301+ {
302+ char * sect_user = NULL , * sect_host = NULL , * sect_port = NULL ;
303+
304+ /* All p_* args must be non-NULL pointers to `char *` string variables
305+ * which may be freed and re-allocated to return normalized values
306+ * (original strings may themselves be NULL).
307+ * The out_* values are optional and may be NULL if you do not want
308+ * those data points returned.
309+ */
310+ if (!p_sect_user || !p_sect_host || !p_sect_port ) {
311+ upslogx (LOG_ERR , "upscli_normalize_auth_section_parts: NULL pointer-to-string argument provided" );
312+ return -1 ;
313+ }
314+
315+ /* No changes imposed here */
316+ sect_user = * p_sect_user ;
317+
318+ sect_host = * p_sect_host ;
319+ if (!sect_host || !* sect_host ) {
320+ sect_host = xstrdup ("localhost" );
321+ if (!sect_host ) goto failed ;
322+ }
323+
324+ sect_port = * p_sect_port ;
325+ if (sect_port && * sect_port ) {
326+ /* As port is a string, resolve it (if not a number,
327+ * try to get one via "services" naming database) */
328+ char * p = sect_port ;
329+ int is_numeric = 1 ;
330+
331+ while (* p ) {
332+ if (!isdigit ((unsigned char )* p )) {
333+ is_numeric = 0 ;
334+ break ;
335+ }
336+ p ++ ;
337+ }
338+
339+ if (!is_numeric ) {
340+ struct servent * se = getservbyname (sect_port , "tcp" );
341+
342+ if (se ) {
343+ char portbuf [16 ];
344+ if (snprintf (portbuf , sizeof (portbuf ), "%u" , ntohs (se -> s_port ) < 1 )) {
345+ upsdebugx (1 , "%s: Failed to construct port number from service name" , __func__ );
346+ goto failed ;
347+ }
348+ sect_port = xstrdup (portbuf );
349+ if (!sect_port ) goto failed ;
350+ } /* else resolution failed, keep original string */
351+ }
352+ } else {
353+ char portbuf [16 ];
354+ if (snprintf (portbuf , sizeof (portbuf ), "%u" , NUT_PORT ) < 1 ) {
355+ upsdebugx (1 , "%s: Failed to construct default port number" , __func__ );
356+ goto failed ;
357+ }
358+ sect_port = xstrdup (portbuf );
359+ if (!sect_port ) goto failed ;
360+ }
361+
362+ /* Only now that we (almost) do not expect failures, we can
363+ * consistently populate caller's output variables (if any) */
364+ if (out_normalized_sect_name ) {
365+ char normalized_sect_name_buf [LARGEBUF ];
366+
367+ if (snprintf (normalized_sect_name_buf , sizeof (normalized_sect_name_buf ), "%s@%s:%s" ,
368+ sect_user ? sect_user : "" ,
369+ sect_host ,
370+ sect_port ) > 0
371+ ) {
372+ free (* out_normalized_sect_name );
373+ * out_normalized_sect_name = xstrdup (normalized_sect_name_buf );
374+ } else {
375+ upsdebugx (1 , "%s: Failed to reconstruct normalized section header" , __func__ );
376+ goto failed ;
377+ }
378+ }
379+
380+ if (out_fixed_sect_user )
381+ * out_fixed_sect_user = (sect_user && * sect_user );
382+
383+ /* Different pointers? */
384+ if (* p_sect_host != sect_host ) {
385+ free (* p_sect_host );
386+ * p_sect_host = sect_host ;
387+ }
388+
389+ if (* p_sect_port != sect_port ) {
390+ free (* p_sect_port );
391+ * p_sect_port = sect_port ;
392+ }
393+
394+ return 0 ;
395+
396+ failed :
397+ free (sect_user );
398+ free (sect_host );
399+ free (sect_port );
400+
401+ return -1 ;
402+ }
403+
295404int upscli_split_auth_section (const char * sect_name ,
296405 char * * normalized_sect_name ,
297406 char * * normalized_sect_user ,
@@ -352,69 +461,16 @@ int upscli_split_auth_section(const char *sect_name,
352461 }
353462
354463 if (colon && colon [1 ]) {
355- /* As port is a string, resolve it (if not a number,
356- * try to get one via "services" naming database) */
357- const char * p = colon + 1 ;
358- int is_numeric = 1 ;
359-
360- while (* p ) {
361- if (!isdigit ((unsigned char )* p )) {
362- is_numeric = 0 ;
363- break ;
364- }
365- p ++ ;
366- }
367-
368- if (is_numeric ) {
369- sect_port = xstrdup (colon + 1 );
370- } else {
371- struct servent * se = getservbyname (colon + 1 , "tcp" );
372-
373- if (se ) {
374- char portbuf [16 ];
375- snprintf (portbuf , sizeof (portbuf ), "%u" , ntohs (se -> s_port ));
376- sect_port = xstrdup (portbuf );
377- } else {
378- /* Resolution failed, fall back to original string */
379- sect_port = xstrdup (colon + 1 );
380- }
381- }
382-
464+ /* May get re-normalized below */
465+ sect_port = xstrdup (colon + 1 );
383466 if (!sect_port ) goto failed ;
384467 }
385468
386- if (!sect_host || !* sect_host ) {
387- free (sect_host );
388- sect_host = xstrdup ("localhost" );
389- if (!sect_host ) goto failed ;
390- }
391-
392- if (!sect_port || !* sect_port ) {
393- free (sect_port );
394- sect_port = xcalloc (6 , sizeof (char ));
395- if (!sect_port ) goto failed ;
396- if (snprintf (sect_port , 6 , "%u" , NUT_PORT ) < 1 ) {
397- upsdebugx (1 , "%s: Failed to construct default port number" , __func__ );
398- goto failed ;
399- }
400- }
401-
402- /* Only now that we (almost) do not expect failures, we can
403- * consistently populate caller's output variables (if any) */
404- if (normalized_sect_name ) {
405- char normalized_sect_name_buf [LARGEBUF ];
406-
407- if (snprintf (normalized_sect_name_buf , sizeof (normalized_sect_name_buf ), "%s@%s:%s" ,
408- sect_user ? sect_user : "" ,
409- sect_host ,
410- sect_port ) > 0
411- ) {
412- * normalized_sect_name = xstrdup (normalized_sect_name_buf );
413- } else {
414- upsdebugx (1 , "%s: Failed to reconstruct normalized section header from '%s'" , __func__ , sect_name );
415- goto failed ;
416- }
417- }
469+ if (upscli_normalize_auth_section_parts (
470+ normalized_sect_name ,
471+ & sect_user , & fixed_sect_user ,
472+ & sect_host , & sect_port ) < 0
473+ ) goto failed ;
418474
419475 if (out_fixed_sect_user )
420476 * out_fixed_sect_user = fixed_sect_user ;
0 commit comments