This one is on the larger side. Therefore I show it before commit. There is also a project that is somewhat active, so someone using this could consider updating to that.
https://github.com/Radmind/radmind/ I only looked briefly. I didn't like the fact that they skip quite some error checking. Index: Makefile =================================================================== RCS file: /cvs/ports/sysutils/radmind/Makefile,v retrieving revision 1.24 diff -u -p -r1.24 Makefile --- Makefile 26 Feb 2021 23:30:53 -0000 1.24 +++ Makefile 10 Jan 2022 20:28:07 -0000 @@ -3,7 +3,7 @@ COMMENT= remote administration software DISTNAME= radmind-1.14.1 -REVISION= 3 +REVISION= 4 CATEGORIES= sysutils HOMEPAGE= http://rsug.itd.umich.edu/software/radmind/ Index: patches/patch-cksum_c =================================================================== RCS file: patches/patch-cksum_c diff -N patches/patch-cksum_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-cksum_c 29 Nov 2021 14:15:35 -0000 @@ -0,0 +1,125 @@ +$OpenBSD$ + +Fix build with opaque EVP_MD_CTX in LibreSSL 3.5. + +Index: cksum.c +--- cksum.c.orig ++++ cksum.c +@@ -41,20 +41,25 @@ do_fcksum( int fd, char *cksum_b64 ) + off_t size = 0; + unsigned char buf[ 8192 ]; + extern EVP_MD *md; +- EVP_MD_CTX mdctx; ++ EVP_MD_CTX *mdctx; + unsigned char md_value[ EVP_MAX_MD_SIZE ]; + +- EVP_DigestInit( &mdctx, md ); ++ if ((mdctx = EVP_MD_CTX_new()) == NULL) { ++ return( -1 ); ++ } ++ EVP_DigestInit( mdctx, md ); + + while (( rr = read( fd, buf, sizeof( buf ))) > 0 ) { + size += rr; +- EVP_DigestUpdate( &mdctx, buf, (unsigned int)rr ); ++ EVP_DigestUpdate( mdctx, buf, (unsigned int)rr ); + } + if ( rr < 0 ) { ++ EVP_MD_CTX_free( mdctx ); + return( -1 ); + } + +- EVP_DigestFinal( &mdctx, md_value, &md_len ); ++ EVP_DigestFinal( mdctx, md_value, &md_len ); ++ EVP_MD_CTX_free( mdctx ); + base64_e( md_value, md_len, cksum_b64 ); + + return( size ); +@@ -103,13 +108,16 @@ do_acksum( char *path, char *cksum_b64, struct applefi + struct as_entry as_entries_endian[ 3 ]; + unsigned int md_len; + extern EVP_MD *md; +- EVP_MD_CTX mdctx; ++ EVP_MD_CTX *mdctx; + unsigned char md_value[ EVP_MAX_MD_SIZE ]; + +- EVP_DigestInit( &mdctx, md ); ++ if ((ctx = EVP_MD_CTX_new()) == NULL) { ++ return( -1 ); ++ } ++ EVP_DigestInit( mdctx, md ); + + /* checksum applesingle header */ +- EVP_DigestUpdate( &mdctx, (char *)&as_header, AS_HEADERLEN ); ++ EVP_DigestUpdate( mdctx, (char *)&as_header, AS_HEADERLEN ); + size += (size_t)AS_HEADERLEN; + + /* endian handling, sum big-endian header entries */ +@@ -120,54 +128,62 @@ do_acksum( char *path, char *cksum_b64, struct applefi + as_entry_netswap( &as_entries_endian[ AS_DFE ] ); + + /* checksum header entries */ +- EVP_DigestUpdate( &mdctx, (char *)&as_entries_endian, ++ EVP_DigestUpdate( mdctx, (char *)&as_entries_endian, + (unsigned int)( 3 * sizeof( struct as_entry ))); + size += sizeof( 3 * sizeof( struct as_entry )); + + /* checksum finder info data */ +- EVP_DigestUpdate( &mdctx, afinfo->ai.ai_data, FINFOLEN ); ++ EVP_DigestUpdate( mdctx, afinfo->ai.ai_data, FINFOLEN ); + size += FINFOLEN; + + /* checksum rsrc fork data */ + if ( afinfo->as_ents[ AS_RFE ].ae_length > 0 ) { + if ( snprintf( rsrc_path, MAXPATHLEN, "%s%s", + path, _PATH_RSRCFORKSPEC ) >= MAXPATHLEN ) { ++ EVP_MD_CTX_free( mdctx ); + errno = ENAMETOOLONG; + return( -1 ); + } + + if (( rfd = open( rsrc_path, O_RDONLY )) < 0 ) { ++ EVP_MD_CTX_free( mdctx ); + return( -1 ); + } + while (( rc = read( rfd, buf, sizeof( buf ))) > 0 ) { +- EVP_DigestUpdate( &mdctx, buf, (unsigned int)rc ); ++ EVP_DigestUpdate( mdctx, buf, (unsigned int)rc ); + size += (size_t)rc; + } + if ( close( rfd ) < 0 ) { ++ EVP_MD_CTX_free( mdctx ); + return( -1 ); + } + if ( rc < 0 ) { ++ EVP_MD_CTX_free( mdctx ); + return( -1 ); + } + } + + if (( dfd = open( path, O_RDONLY, 0 )) < 0 ) { ++ EVP_MD_CTX_free( mdctx ); + return( -1 ); + } + /* checksum data fork */ + while (( rc = read( dfd, buf, sizeof( buf ))) > 0 ) { +- EVP_DigestUpdate( &mdctx, buf, (unsigned int)rc ); ++ EVP_DigestUpdate( mdctx, buf, (unsigned int)rc ); + size += (size_t)rc; + } + if ( rc < 0 ) { ++ EVP_MD_CTX_free( mdctx ); + return( -1 ); + } + if ( close( dfd ) < 0 ) { ++ EVP_MD_CTX_free( mdctx ); + return( -1 ); + } + +- EVP_DigestFinal( &mdctx, md_value, &md_len ); ++ EVP_DigestFinal( mdctx, md_value, &md_len ); + base64_e( ( char*)&md_value, md_len, cksum_b64 ); ++ EVP_MD_CTX_free( mdctx ); + + return( size ); + } Index: patches/patch-retr_c =================================================================== RCS file: patches/patch-retr_c diff -N patches/patch-retr_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-retr_c 29 Nov 2021 14:18:49 -0000 @@ -0,0 +1,313 @@ +$OpenBSD$ + +Fix build with opaque EVP_MD_CTX in LibreSSL 3.5. + +Index: retr.c +--- retr.c.orig ++++ retr.c +@@ -74,7 +74,7 @@ retr( SNET *sn, char *pathdesc, char *path, char *temp + char buf[ 8192 ]; + ssize_t rr; + extern EVP_MD *md; +- EVP_MD_CTX mdctx; ++ EVP_MD_CTX *mdctx = NULL; + unsigned char md_value[ EVP_MAX_MD_SIZE ]; + char cksum_b64[ SZ_BASE64_E( EVP_MAX_MD_SIZE ) ]; + +@@ -84,26 +84,32 @@ retr( SNET *sn, char *pathdesc, char *path, char *temp + fprintf( stderr, "%s\n", pathdesc ); + return( 1 ); + } +- EVP_DigestInit( &mdctx, md ); ++ mdctx = EVP_MD_CTX_new(); ++ if ( mdctx == NULL) { ++ fprintf( stderr, "EVP_MD_CTX_new failed\n" ); ++ goto error0; ++ } ++ EVP_DigestInit( mdctx, md ); + } + + if ( verbose ) printf( ">>> RETR %s\n", pathdesc ); + if ( snet_writef( sn, "RETR %s\n", pathdesc ) < 0 ) { + fprintf( stderr, "retrieve %s failed: 1-%s\n", pathdesc, + strerror( errno )); +- return( -1 ); ++ goto error0; + } + + tv = timeout; + if (( line = snet_getline_multi( sn, logger, &tv )) == NULL ) { + fprintf( stderr, "retrieve %s failed: 2-%s\n", pathdesc, + strerror( errno )); +- return( -1 ); ++ goto error0; + } + + if ( *line != '2' ) { + fprintf( stderr, "%s\n", line ); +- return( 1 ); ++ returnval = 1; ++ goto error0; + } + + /* Get file size from server */ +@@ -111,7 +117,7 @@ retr( SNET *sn, char *pathdesc, char *path, char *temp + if (( line = snet_getline( sn, &tv )) == NULL ) { + fprintf( stderr, "retrieve %s failed: 3-%s\n", pathdesc, + strerror( errno )); +- return( -1 ); ++ goto error0; + } + size = strtoofft( line, NULL, 10 ); + if ( verbose ) printf( "<<< %" PRIofft "d\n", size ); +@@ -119,7 +125,7 @@ retr( SNET *sn, char *pathdesc, char *path, char *temp + fprintf( stderr, "line %d: size in transcript does not match size " + "from server\n", linenum ); + fprintf( stderr, "%s\n", pathdesc ); +- return( -1 ); ++ goto error0; + } + + /*Create temp file name*/ +@@ -127,7 +133,7 @@ retr( SNET *sn, char *pathdesc, char *path, char *temp + path, getpid()) >= MAXPATHLEN ) { + fprintf( stderr, "%s.radmind.%i: too long", path, + (int)getpid()); +- return( -1 ); ++ goto error0; + } + /* Open file */ + if (( fd = open( temppath, O_WRONLY | O_CREAT, tempmode )) < 0 ) { +@@ -135,15 +141,15 @@ retr( SNET *sn, char *pathdesc, char *path, char *temp + errno = 0; + if ( mkprefix( temppath ) != 0 ) { + perror( temppath ); +- return( -1 ); ++ goto error0; + } + if (( fd = open( temppath, O_WRONLY | O_CREAT, tempmode )) < 0 ) { + perror( temppath ); +- return( -1 ); ++ goto error0; + } + } else { + perror( temppath ); +- return( -1 ); ++ goto error0; + } + } + +@@ -165,7 +171,7 @@ retr( SNET *sn, char *pathdesc, char *path, char *temp + goto error2; + } + if ( cksum ) { +- EVP_DigestUpdate( &mdctx, buf, (unsigned int)rr ); ++ EVP_DigestUpdate( mdctx, buf, (unsigned int)rr ); + } + if ( dodots ) { putc( '.', stdout ); fflush( stdout ); } + size -= rr; +@@ -197,7 +203,7 @@ retr( SNET *sn, char *pathdesc, char *path, char *temp + + /* cksum file */ + if ( cksum ) { +- EVP_DigestFinal( &mdctx, md_value, &md_len ); ++ EVP_DigestFinal( mdctx, md_value, &md_len ); + base64_e( md_value, md_len, cksum_b64 ); + if ( strcmp( trancksum, cksum_b64 ) != 0 ) { + fprintf( stderr, "line %d: checksum in transcript does not match " +@@ -208,12 +214,15 @@ retr( SNET *sn, char *pathdesc, char *path, char *temp + } + } + ++ EVP_MD_CTX_free( mdctx ); + return( 0 ); + + error2: + close( fd ); + error1: + unlink( temppath ); ++error0: ++ EVP_MD_CTX_free( mdctx ); + return( returnval ); + } + +@@ -246,7 +255,7 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + struct as_entry ae_ents[ 3 ]; + struct timeval tv; + extern EVP_MD *md; +- EVP_MD_CTX mdctx; ++ EVP_MD_CTX *mdctx = NULL; + unsigned char md_value[ EVP_MAX_MD_SIZE ]; + char cksum_b64[ SZ_BASE64_E( EVP_MAX_MD_SIZE ) ]; + +@@ -256,26 +265,29 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + fprintf( stderr, "%s\n", pathdesc ); + return( 1 ); + } +- EVP_DigestInit( &mdctx, md ); ++ if ( ( mdctx = EVP_MD_CTX_new( ) ) == NULL ) ++ return( -1 ); ++ EVP_DigestInit( mdctx, md ); + } + + if ( verbose ) printf( ">>> RETR %s\n", pathdesc ); + if ( snet_writef( sn, "RETR %s\n", pathdesc ) < 0 ) { + fprintf( stderr, "retrieve applefile %s failed: 1-%s\n", pathdesc, + strerror( errno )); +- return( -1 ); ++ goto error0; + } + + tv = timeout; + if (( line = snet_getline_multi( sn, logger, &tv )) == NULL ) { + fprintf( stderr, "retrieve applefile %s failed: 2-%s\n", pathdesc, + strerror( errno )); +- return( -1 ); ++ goto error0; + } + + if ( *line != '2' ) { + fprintf( stderr, "%s\n", line ); +- return( 1 ); ++ returnval = 1; ++ goto error0; + } + + /* Get file size from server */ +@@ -283,7 +295,7 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + if (( line = snet_getline( sn, &tv )) == NULL ) { + fprintf( stderr, "retrieve applefile %s failed: 3-%s\n", pathdesc, + strerror( errno )); +- return( -1 ); ++ goto error0; + } + size = strtoofft( line, NULL, 10 ); + if ( verbose ) printf( "<<< %" PRIofft "d\n", size ); +@@ -291,14 +303,14 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + fprintf( stderr, "line %d: size in transcript does not match size" + "from server\n", linenum ); + fprintf( stderr, "%s\n", pathdesc ); +- return( -1 ); ++ goto error0; + } + if ( size < ( AS_HEADERLEN + ( 3 * sizeof( struct as_entry )) + + FINFOLEN )) { + fprintf( stderr, + "retrieve applefile %s failed: AppleSingle-encoded file too " + "short\n", path ); +- return( -1 ); ++ goto error0; + } + + /* read header to determine if file is encoded in applesingle */ +@@ -306,24 +318,24 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + if (( rc = snet_read( sn, ( char * )&ah, AS_HEADERLEN, &tv )) <= 0 ) { + fprintf( stderr, "retrieve applefile %s failed: 4-%s\n", pathdesc, + strerror( errno )); +- return( -1 ); ++ goto error0; + } + if (( rc != AS_HEADERLEN ) || + ( memcmp( &as_header, &ah, AS_HEADERLEN ) != 0 )) { + fprintf( stderr, + "retrieve applefile %s failed: corrupt AppleSingle-encoded file\n", + path ); +- return( -1 ); ++ goto error0; + } + if ( cksum ) { +- EVP_DigestUpdate( &mdctx, (char *)&ah, (unsigned int)rc ); ++ EVP_DigestUpdate( mdctx, (char *)&ah, (unsigned int)rc ); + } + + /* name temp file */ + if ( snprintf( temppath, MAXPATHLEN, "%s.radmind.%i", path, + getpid()) >= MAXPATHLEN ) { + fprintf( stderr, "%s.radmind.%i: too long", path, ( int )getpid()); +- return( -1 ); ++ goto error0; + } + + /* data fork must exist to write to rsrc fork */ +@@ -333,16 +345,16 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + errno = 0; + if ( mkprefix( temppath ) != 0 ) { + perror( temppath ); +- return( -1 ); ++ goto error0; + } + if (( dfd = open( temppath, O_CREAT | O_EXCL | O_WRONLY, + tempmode )) < 0 ) { + perror( temppath ); +- return( -1 ); ++ goto error0; + } + } else { + perror( temppath ); +- return( -1 ); ++ goto error0; + } + } + +@@ -373,7 +385,7 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + /* Should we check for valid ae_ents here? YES! */ + + if ( cksum ) { +- EVP_DigestUpdate( &mdctx, (char *)&ae_ents, (unsigned int)rc ); ++ EVP_DigestUpdate( mdctx, (char *)&ae_ents, (unsigned int)rc ); + } + if ( dodots ) { putc( '.', stdout ); fflush( stdout ); } + +@@ -398,7 +410,7 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + goto error2; + } + if ( cksum ) { +- EVP_DigestUpdate( &mdctx, finfo, (unsigned int)rc ); ++ EVP_DigestUpdate( mdctx, finfo, (unsigned int)rc ); + } + if ( dodots ) { putc( '.', stdout ); fflush( stdout ); } + size -= rc; +@@ -448,7 +460,7 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + goto error3; + } + if ( cksum ) { +- EVP_DigestUpdate( &mdctx, buf, (unsigned int)rc ); ++ EVP_DigestUpdate( mdctx, buf, (unsigned int)rc ); + } + if ( dodots ) { putc( '.', stdout ); fflush( stdout ); } + if ( showprogress ) { +@@ -482,7 +494,7 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + } + + if ( cksum ) { +- EVP_DigestUpdate( &mdctx, buf, (unsigned int)rc ); ++ EVP_DigestUpdate( mdctx, buf, (unsigned int)rc ); + } + if ( dodots ) { putc( '.', stdout ); fflush( stdout); } + if ( showprogress ) { +@@ -523,7 +535,7 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + if ( verbose ) printf( "<<< .\n" ); + + if ( cksum ) { +- EVP_DigestFinal( &mdctx, md_value, &md_len ); ++ EVP_DigestFinal( mdctx, md_value, &md_len ); + base64_e(( char*)&md_value, md_len, cksum_b64 ); + if ( strcmp( trancksum, cksum_b64 ) != 0 ) { + fprintf( stderr, "line %d: checksum in transcript does not match " +@@ -534,6 +546,7 @@ retr_applefile( SNET *sn, char *pathdesc, char *path, + } + } + ++ EVP_MD_CTX_free( mdctx ); + return( 0 ); + + error3: +@@ -542,6 +555,8 @@ error2: + close( dfd ); + error1: + unlink( temppath ); ++error0: ++ EVP_MD_CTX_free( mdctx ); + return( returnval ); + } + Index: patches/patch-stor_c =================================================================== RCS file: patches/patch-stor_c diff -N patches/patch-stor_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-stor_c 29 Nov 2021 14:17:32 -0000 @@ -0,0 +1,70 @@ +$OpenBSD$ + +Fix build with opaque EVP_MD_CTX in LibreSSL 3.5. + +Index: stor.c +--- stor.c.orig ++++ stor.c +@@ -136,7 +136,7 @@ stor_file( SNET *sn, char *pathdesc, char *path, off_t + ssize_t rr, size = 0; + unsigned int md_len; + extern EVP_MD *md; +- EVP_MD_CTX mdctx; ++ EVP_MD_CTX *mdctx = NULL; + unsigned char md_value[ EVP_MAX_MD_SIZE ]; + char cksum_b64[ SZ_BASE64_E( EVP_MAX_MD_SIZE ) ]; + +@@ -146,7 +146,12 @@ stor_file( SNET *sn, char *pathdesc, char *path, off_t + fprintf( stderr, "line %d: No checksum listed\n", linenum ); + exit( 2 ); + } +- EVP_DigestInit( &mdctx, md ); ++ mdctx = EVP_MD_CTX_new( ); ++ if ( mdctx == NULL ) { ++ fprintf( stderr, "EVP_MD_CTX_new failed\n"); ++ exit( 2 ); ++ } ++ EVP_DigestInit( mdctx, md ); + } + + /* Open and stat file */ +@@ -197,12 +202,13 @@ stor_file( SNET *sn, char *pathdesc, char *path, off_t + if ( snet_write( sn, buf, rr, &tv ) != rr ) { + fprintf( stderr, "stor_file %s failed: %s\n", pathdesc, + strerror( errno )); ++ EVP_MD_CTX_free( mdctx ); + return( -1 ); + } + size -= rr; + if ( dodots ) { putc( '.', stdout ); fflush( stdout ); } + if ( cksum ) { +- EVP_DigestUpdate( &mdctx, buf, (unsigned int)rr ); ++ EVP_DigestUpdate( mdctx, buf, (unsigned int)rr ); + } + + if ( showprogress ) { +@@ -226,6 +232,7 @@ stor_file( SNET *sn, char *pathdesc, char *path, off_t + if ( snet_writef( sn, ".\r\n" ) < 0 ) { + fprintf( stderr, "stor_file %s failed: %s\n", pathdesc, + strerror( errno )); ++ EVP_MD_CTX_free( mdctx ); + return( -1 ); + } + if ( verbose ) fputs( "\n>>> .\n", stdout ); +@@ -237,7 +244,7 @@ stor_file( SNET *sn, char *pathdesc, char *path, off_t + + /* cksum data sent */ + if ( cksum ) { +- EVP_DigestFinal( &mdctx, md_value, &md_len ); ++ EVP_DigestFinal( mdctx, md_value, &md_len ); + base64_e( md_value, md_len, cksum_b64 ); + if ( strcmp( trancksum, cksum_b64 ) != 0 ) { + fprintf( stderr, +@@ -247,6 +254,7 @@ stor_file( SNET *sn, char *pathdesc, char *path, off_t + } + + if ( !quiet && !showprogress ) printf( "%s: stored\n", path ); ++ EVP_MD_CTX_free( mdctx ); + return( 0 ); + } +
