@@ -85,12 +85,13 @@ journal_fdopen(int fd, const char *journal_path,
8585}
8686
8787static int
88- journal_mkstemp (const char * parent_dir , char * pathbuf , size_t pathsize )
88+ journal_mkuuid (const char * parent_dir , char * pathbuf , size_t pathsize )
8989{
9090 int len , dfd = -1 , fd = -1 ;
9191 mode_t dirmode , oldmask ;
92- char * template ;
93- debug_decl (journal_mkstemp , SUDO_DEBUG_UTIL );
92+ unsigned char uuid [16 ];
93+ char uuid_str [37 ];
94+ debug_decl (journal_mkuuid , SUDO_DEBUG_UTIL );
9495
9596 /* umask must not be more restrictive than the file modes. */
9697 dirmode = logsrvd_conf_iolog_mode () | S_IXUSR ;
@@ -100,24 +101,35 @@ journal_mkstemp(const char *parent_dir, char *pathbuf, size_t pathsize)
100101 dirmode |= S_IXOTH ;
101102 oldmask = umask (ACCESSPERMS & ~dirmode );
102103
103- len = snprintf (pathbuf , pathsize , "%s/%s/%s" ,
104- logsrvd_conf_relay_dir (), parent_dir , RELAY_TEMPLATE );
105- if ((size_t )len >= pathsize ) {
106- errno = ENAMETOOLONG ;
107- sudo_warn ("%s/%s/%s" , logsrvd_conf_relay_dir (), parent_dir ,
108- RELAY_TEMPLATE );
109- goto done ;
110- }
111- dfd = sudo_open_parent_dir (pathbuf , logsrvd_conf_iolog_uid (),
112- logsrvd_conf_iolog_gid (), S_IRWXU |S_IXGRP |S_IXOTH , false);
113- if (dfd == -1 ) {
114- sudo_debug_printf (SUDO_DEBUG_ERROR |SUDO_DEBUG_LINENO |SUDO_DEBUG_ERRNO ,
115- "unable to create parent dir for %s" , pathbuf );
116- goto done ;
117- }
118- template = & pathbuf [(size_t )len - (sizeof (RELAY_TEMPLATE ) - 1 )];
119- if ((fd = mkostempsat (dfd , template , 0 , 0 )) == -1 ) {
120- sudo_warn (U_ ("%s: %s" ), "mkstemp" , pathbuf );
104+ do {
105+ sudo_uuid_create (uuid );
106+ if (sudo_uuid_to_string (uuid , uuid_str , sizeof (uuid_str )) == NULL ) {
107+ sudo_warnx ("%s" , U_ ("unable to generate UUID" ));
108+ goto done ;
109+ }
110+
111+ len = snprintf (pathbuf , pathsize , "%s/%s/%s" ,
112+ logsrvd_conf_relay_dir (), parent_dir , uuid_str );
113+ if ((size_t )len >= pathsize ) {
114+ errno = ENAMETOOLONG ;
115+ sudo_warn ("%s/%s/%s" ,
116+ logsrvd_conf_relay_dir (), parent_dir , uuid_str );
117+ goto done ;
118+ }
119+ if (dfd == -1 ) {
120+ dfd = sudo_open_parent_dir (pathbuf , logsrvd_conf_iolog_uid (),
121+ logsrvd_conf_iolog_gid (), S_IRWXU |S_IXGRP |S_IXOTH , false);
122+ if (dfd == -1 ) {
123+ sudo_debug_printf (
124+ SUDO_DEBUG_ERROR |SUDO_DEBUG_LINENO |SUDO_DEBUG_ERRNO ,
125+ "unable to create parent dir for %s" , pathbuf );
126+ goto done ;
127+ }
128+ }
129+ fd = openat (dfd , uuid_str , O_CREAT |O_EXCL |O_RDWR , S_IRUSR |S_IWUSR );
130+ } while (fd == -1 && errno == EEXIST );
131+ if (fd == -1 ) {
132+ sudo_warn (U_ ("%s: %s" ), "openat" , pathbuf );
121133 goto done ;
122134 }
123135
@@ -139,7 +151,7 @@ journal_create(struct connection_closure *closure)
139151 int fd ;
140152 debug_decl (journal_create , SUDO_DEBUG_UTIL );
141153
142- fd = journal_mkstemp ("incoming" , journal_path , sizeof (journal_path ));
154+ fd = journal_mkuuid ("incoming" , journal_path , sizeof (journal_path ));
143155 if (fd == -1 ) {
144156 closure -> errstr = _ ("unable to create journal file" );
145157 debug_return_bool (false);
@@ -183,7 +195,7 @@ journal_finish(struct connection_closure *closure)
183195 rewind (closure -> journal );
184196
185197 /* Move journal to the outgoing directory. */
186- fd = journal_mkstemp ("outgoing" , outgoing_path , sizeof (outgoing_path ));
198+ fd = journal_mkuuid ("outgoing" , outgoing_path , sizeof (outgoing_path ));
187199 if (fd == -1 ) {
188200 closure -> errstr = _ ("unable to rename journal file" );
189201 debug_return_bool (false);
@@ -405,23 +417,30 @@ static bool
405417journal_restart (const RestartMessage * msg , const uint8_t * buf , size_t buflen ,
406418 struct connection_closure * closure )
407419{
420+ char uuid_str [37 ], journal_path [PATH_MAX ];
421+ unsigned char uuid [16 ];
408422 struct timespec target ;
409423 int fd , len ;
410- char * cp , journal_path [PATH_MAX ];
411424 debug_decl (journal_restart , SUDO_DEBUG_UTIL );
412425
413- /* Strip off leading hostname from log_id. */
414- if ((cp = strchr (msg -> log_id , '/' )) != NULL ) {
415- if (cp != msg -> log_id )
416- cp ++ ;
417- } else {
418- cp = msg -> log_id ;
426+ /* A journal log_id must be a base64-encoded UUID. */
427+ if (strlen (msg -> log_id ) != ((16 + 2 ) / 3 * 4 ))
428+ goto parse_err ;
429+ if (sudo_base64_decode (msg -> log_id , uuid , sizeof (uuid )) != sizeof (uuid ))
430+ goto parse_err ;
431+ if (sudo_uuid_to_string (uuid , uuid_str , sizeof (uuid_str )) == NULL ) {
432+ parse_err :
433+ sudo_warnx (U_ ("%s: %s" ), __func__ , U_ ("unable to parse log_id" ));
434+ closure -> errstr = _ ("unable to open journal file" );
435+ debug_return_bool (false);
419436 }
437+
438+ /* Journal files are stored by UUID. */
420439 len = snprintf (journal_path , sizeof (journal_path ), "%s/incoming/%s" ,
421- logsrvd_conf_relay_dir (), cp );
440+ logsrvd_conf_relay_dir (), uuid_str );
422441 if (len >= ssizeof (journal_path )) {
423442 errno = ENAMETOOLONG ;
424- sudo_warn ("%s/incoming/%s" , logsrvd_conf_relay_dir (), cp );
443+ sudo_warn ("%s/incoming/%s" , logsrvd_conf_relay_dir (), uuid_str );
425444 closure -> errstr = _ ("unable to open journal file" );
426445 debug_return_bool (false);
427446 }
@@ -498,7 +517,19 @@ journal_accept(const AcceptMessage *msg, const uint8_t *buf, size_t len,
498517
499518 if (msg -> expect_iobufs ) {
500519 /* Send log ID to client for restarting connections. */
501- if (!fmt_log_id_message (closure -> journal_path , closure ))
520+ unsigned char uuid [16 ];
521+ const char * uuid_str ;
522+
523+ /* Journaled I/O log files are files stored by UUID. */
524+ uuid_str = strrchr (closure -> journal_path , '/' );
525+ if (uuid_str == NULL )
526+ debug_return_bool (false);
527+ uuid_str ++ ;
528+
529+ /* Parse UUID and format as a log ID (base64-encoded). */
530+ if (sudo_uuid_from_string (uuid_str , uuid ) != 0 )
531+ debug_return_bool (false);
532+ if (!fmt_log_id_message (uuid , "" , closure ))
502533 debug_return_bool (false);
503534 if (sudo_ev_add (closure -> evbase , closure -> write_ev ,
504535 logsrvd_conf_server_timeout (), false) == -1 ) {
0 commit comments