char * path_normalize( char *path ) { pem_t *pemp = pem_alloc( path ); pa_t *pap = pa_alloc( ); char *pep; char *npath; ASSERT( path[ 0 ] == '/' ); while ( ( pep = pem_next( pemp )) != 0 ) { if ( ! strcmp( pep, "" )) { free( ( void * )pep ); continue; } if ( ! strcmp( pep, "." )) { free( ( void * )pep ); continue; } if ( ! strcmp( pep, ".." )) { int ok; free( ( void * )pep ); ok = pa_peel( pap ); if ( ! ok ) { pa_free( pap ); pem_free( pemp ); return 0; } continue; } pa_append( pap, pep ); } npath = pa_gen( pap ); pa_free( pap ); pem_free( pemp ); return npath; }
/** * Locate boundary marker line * * @v image PEM image * @v offset Starting offset * @v marker Boundary marker * @ret offset Offset to boundary marker line, or negative error */ static int pem_marker ( struct image *image, size_t offset, const char *marker ) { char buf[ strlen ( marker ) ]; /* Sanity check */ assert ( offset <= image->len ); /* Scan for marker at start of line */ while ( offset < image->len ) { /* Check for marker */ if ( ( image->len - offset ) < sizeof ( buf ) ) break; copy_from_user ( buf, image->data, offset, sizeof ( buf ) ); if ( memcmp ( buf, marker, sizeof ( buf ) ) == 0 ) return offset; /* Move to next line */ offset = pem_next ( image, offset ); assert ( offset <= image->len ); } return -ENOENT; }
/** * Extract ASN.1 object from image * * @v image PEM image * @v offset Offset within image * @v cursor ASN.1 cursor to fill in * @ret next Offset to next image, or negative error * * The caller is responsible for eventually calling free() on the * allocated ASN.1 cursor. */ static int pem_asn1 ( struct image *image, size_t offset, struct asn1_cursor **cursor ) { size_t encoded_len; size_t decoded_max_len; char *encoded; void *decoded; int begin; int end; int len; int rc; /* Locate and skip BEGIN marker */ begin = pem_marker ( image, offset, PEM_BEGIN ); if ( begin < 0 ) { rc = begin; DBGC ( image, "PEM %s [%#zx,%#zx) missing BEGIN marker: %s\n", image->name, offset, image->len, strerror ( rc ) ); goto err_begin; } begin = pem_next ( image, begin ); /* Locate and skip END marker */ end = pem_marker ( image, begin, PEM_END ); if ( end < 0 ) { rc = end; DBGC ( image, "PEM %s [%#zx,%#zx) missing END marker: %s\n", image->name, offset, image->len, strerror ( rc ) ); goto err_end; } encoded_len = ( end - begin ); end = pem_next ( image, end ); /* Extract Base64-encoded data */ encoded = malloc ( encoded_len + 1 /* NUL */ ); if ( ! encoded ) { rc = -ENOMEM; goto err_alloc_encoded; } copy_from_user ( encoded, image->data, begin, encoded_len ); encoded[encoded_len] = '\0'; /* Allocate cursor and data buffer */ decoded_max_len = base64_decoded_max_len ( encoded ); *cursor = malloc ( sizeof ( **cursor ) + decoded_max_len ); if ( ! *cursor ) { rc = -ENOMEM; goto err_alloc_cursor; } decoded = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) ); /* Decode Base64-encoded data */ len = base64_decode ( encoded, decoded, decoded_max_len ); if ( len < 0 ) { rc = len; DBGC ( image, "PEM %s could not decode: %s\n", image->name, strerror ( rc ) ); goto err_decode; } (*cursor)->data = decoded; (*cursor)->len = len; assert ( (*cursor)->len <= decoded_max_len ); /* Free Base64-encoded data */ free ( encoded ); /* Update offset and skip any unencapsulated trailer */ offset = end; if ( pem_marker ( image, offset, PEM_BEGIN ) < 0 ) offset = image->len; return offset; err_decode: free ( *cursor ); *cursor = NULL; err_alloc_cursor: free ( encoded ); err_alloc_encoded: err_end: err_begin: return rc; }