*/ class ParTCP_Local_Id_Messages { static function handle_root_registration( $message, $receipt ){ global $Config, $FileSystem, $LocalId, $ServerData, $Timestamp; if ( $LocalId->registrations_exist() ){ $receipt->set_rejection( 41, _('Root registration has already been performed') ); return $receipt->dump( TRUE ); } list ( $id, $server ) = explode( '@', $message->get('Participant-Id') ) + [ '', '' ]; if ( ! empty( $server ) && $server != $ServerData['name'] ){ $receipt->set_rejection( 42, _('Participant ID has invalid domain') ); return $receipt->dump( TRUE ); } $dir = $LocalId->get_dir( $id ); $success = $FileSystem->make_dir( $dir ); if ( ! $success ){ $receipt->set_failure( sprintf( _('Could not create participant directory %s'), $dir ) ); return $receipt->dump( TRUE ); } $fileName = date( 'Ymd-His', $Timestamp ) . '-registration'; $receipt->set( 'Message-Type', 'registration-confirmation' ); $credential = $message->get('Credential'); $name = $message->get('Name'); $receipt->set( 'Participant-Data', compact( 'id', 'name', 'credential' ) ); $receiptString = $receipt->dump( TRUE ); $FileSystem->put_contents( "{$dir}/{$fileName}", $receiptString ); return $receiptString; } static function handle_registration( $message, $receipt ){ global $Config, $FileSystem, $LocalId, $ServerData, $Timestamp; $firstReg = ! $LocalId->registrations_exist(); $object = [ 'type' => 'server', 'id' => '', 'dir' => '/' ]; if ( ! $firstReg && ! ptcp_is_authorized( $message->get('From'), 'registration', $object ) ){ $receipt->set_rejection( 31, _('Sender is not authorized to register participants') ); return $receipt->dump( TRUE ); } if ( ! empty( $ServerData['consent_statement'] ) && ( ! $message->get('Consent-Statement') || trim( $ServerData['consent_statement'] ) != trim( $message->get('Consent-Statement') ) ) ){ $receipt->set_rejection( 41, _('Missing or differing consent statement') ); return $receipt->dump( TRUE ); } $id = $message->get('Participant-Id'); if ( ! empty( $id ) ){ // create participant with specific id, if needed list ( $id, $server ) = explode( '@', $id ) + [ '', '' ]; if ( ! empty( $server ) && $server != $ServerData['name'] ){ $receipt->set_rejection( 42, _('Participant ID has invalid domain') ); return $receipt->dump( TRUE ); } $dir = $LocalId->get_dir( $id ); $existingData = $LocalId->get_data( $id ); if ( ! $existingData ){ $success = $FileSystem->make_dir( $dir ); if ( ! $success ){ $receipt->set_failure( sprintf( _('Could not create participant directory %s'), $dir ) ); return $receipt->dump( TRUE ); } $name = $message->get('Name'); } elseif ( ! $message->get('Update-If-Existent') ){ $receipt->set_rejection( 43, sprintf( _('Participant %s already exists'), $id ) ); return $receipt->dump( TRUE ); } } else { // create participant with randomly generated id $counter = 0; $name = str_replace( '+', '-', $message->get('Name') ); do { $counter++; $code = rand( 10000, 99999 ); $id = "{$name}.{$code}"; $dir = $LocalId->get_dir( $id ); $success = $FileSystem->make_dir( $dir ); } while ( ! $success && $counter < 10 ); } if ( empty( $existingData ) ){ $data = [ 'id' => $id, 'name' => $name, 'credential' => $message->get('Credential'), 'credential_permanence' => $message->get('Credential-Permanence'), 'flags' => $message->get('Flags'), ]; $attributes = $message->get('Attributes'); if ( $attributes ){ $data['attributes'] = ptcp_local_encrypt( $attributes ); } } else { $data = $existingData; if ( $name = $message->get('Name') ){ $data['name'] = $name; } if ( $flags = $message->get('Flags') ){ $data['flags'] = $flags; } $attributes = $message->get('Attributes'); if ( ! $attributes ){ unset( $data['attributes'] ); } else { $attributes = array_merge( $data['attributes'] ?? [], $attributes ); $attributes = array_filter( $attributes, function( $v ){ return ! is_null( $v ); } ); $data['attributes'] = ptcp_local_encrypt( $attributes ); } $data = array_filter( $data, function( $v ){ return ! is_null( $v ); } ); } $fileName = date( 'Ymd-His', $Timestamp ) . '-registration'; $receipt->set( 'Message-Type', 'registration-confirmation' ); $receipt->set( 'Participant-Data', $data ); $receiptString = $receipt->dump( TRUE ); $FileSystem->put_contents( "{$dir}/{$fileName}", $receiptString ); $data['attributes'] = $message->get('Attributes'); $receipt->set( 'Participant-Data', $data, TRUE ); return $receipt->dump( TRUE ); } static function handle_participant_update_request( $message, $receipt ){ global $Config, $FileSystem, $LocalId, $ServerData, $Timestamp; if ( ! ptcp_is_authorized( $message->get('From'), 'participant-update-request', [ 'type' => 'server', 'id' => '', 'dir' => '/' ] ) ){ $receipt->set_rejection( 31, _('Sender is not authorized to update participants') ); return $receipt->dump( TRUE ); } $id = $message->get('Participant-Id'); list ( $id, $server ) = explode( '@', $id ) + [ '', '' ]; if ( ! empty( $server ) && $server != $ServerData['name'] ){ $receipt->set_rejection( 41, _('Participant ID has invalid domain') ); return $receipt->dump( TRUE ); } $data = $LocalId->get_data( $id ); if ( ! $data ){ $receipt->set_rejection( 42, sprintf( _('Participant %s does not exist'), $id ) ); return $receipt->dump( TRUE ); } if ( $name = $message->get('Name') ){ $data['name'] = $name; } if ( $flags = $message->get('Flags') ){ $data['flags'] = $flags; } if ( $flagsToAdd = $message->get('Add-Flags') ){ $data['flags'] = array_unique( array_merge( $data['flags'], $flagsToAdd ) ); } if ( $flagsToRemove = $message->get('Remove-Flags') ){ $data['flags'] = array_diff( $data['flags'], $flagsToRemove ); } $attributes = $message->get('Attributes'); if ( ! $attributes ){ unset( $data['attributes'] ); } else { $attributes = array_merge( $data['attributes'] ?? [], $attributes ); $attributes = array_filter( $attributes, function( $v ){ return ! is_null( $v ); } ); $data['attributes'] = ptcp_local_encrypt( $attributes ); } $data = array_filter( $data, function( $v ){ return ! is_null( $v ); } ); $dir = $LocalId->get_dir( $id ); $fileName = date( 'Ymd-His', $Timestamp ) . '-participant-update-request'; $receipt->set( 'Message-Type', 'participant-details' ); $receipt->set( 'Participant-Data', $data ); $receiptString = $receipt->dump( TRUE ); $FileSystem->put_contents( "{$dir}/{$fileName}", $receiptString ); if ( $attributes ){ $data['attributes'] = $attributes; } $receipt->set( 'Participant-Data', $data, TRUE ); return $receipt->dump( TRUE ); } static function handle_key_submission( $message, $receipt ){ global $Config, $Counter, $Events, $FileSystem, $LocalId, $ServerData, $Timestamp; list ( $id, $server ) = explode( '@', $message->get('From') ) + [ '', '' ]; if ( ! empty( $server ) && $server != $ServerData['name'] ){ $receipt->set_rejection( 31, _('Invalid sender domain') ); return $receipt->dump( TRUE ); } if ( is_object( $Events ) ){ if ( strpos( $id, '+' ) ){ list( $eventId, $id ) = explode( '+', $id ); } if ( ! empty( $eventId ) || ( $eventId = $message->get('Event-Id') ) ){ $eventData = $Events->get_data( $eventId ); $eventDir = $Events->get_dir( $eventId ); $LocalId->set_base_dir( $eventDir ); $pseudoId = TRUE; $receipt->set('Date'); } } if ( empty( $pseudoId ) && ! $message->get('Date') ){ $receipt->set_rejection( 21, _('Date is mandatory when using open identity') ); return $receipt->dump( TRUE ); } elseif ( ! empty( $pseudoId ) && $message->get('Date') ){ $receipt->set_rejection( 22, _('Date must be omitted when using pseudo identity') ); return $receipt->dump( TRUE ); } $ignoreCredential = ! empty( $eventData['is_demo'] ); $data = $LocalId->get_data( $id ); if ( ! $data ){ $receipt->set_rejection( 41, sprintf( _('Unknown participant %s'), $id ) ); return $receipt->dump( TRUE ); } if ( ! $ignoreCredential && ( empty( $data['credential'] ) || trim( $data['credential'] ) != hash( 'sha256', trim( $message->get('Credential') ) ) ) ){ $receipt->set_rejection( 32, _('Wrong credential or key submission not permitted') ); return $receipt->dump( TRUE ); } $data['public_key'] = trim( $message->get('Public-Key') ); if ( empty( $data['credential_permanence'] ) ){ unset( $data['credential'] ); } $receipt->set( 'Participant-Data', $data ); $fileName = date( 'Ymd-His', $Timestamp ) . '-key-submission'; $dir = $LocalId->get_dir( $id ); $receiptString = $receipt->dump( TRUE ); $FileSystem->put_contents( "{$dir}/{$fileName}", $receiptString ); if ( ! empty( $eventDir ) ){ $Counter->set_base_dir( $eventDir ); $Counter->increment('key-submissions'); } return $receiptString; } static function handle_key_renewal_permission( $message, $receipt ){ global $FileSystem, $LocalId, $Timestamp; $object = [ 'type' => 'server', 'id' => '', 'dir' => '/' ]; if ( ! ptcp_is_authorized( $message->get('From'), 'registration', $object ) ){ $receipt->set_rejection( 31, _('Sender is not authorized to permit key submissions') ); return $receipt->dump( TRUE ); } $ptcpId = $message->get('Participant-Id'); $data = $LocalId->get_data( $ptcpId ); if ( ! $data ){ $receipt->set_rejection( 41, sprintf( _('Unknown participant %s'), $ptcpId ) ); return $receipt->dump( TRUE ); } $data['credential'] = $message->get('Credential'); $data['credential_permanence'] = $message->get('Credential-Permanence'); $receipt->set( 'Participant-Data', $data ); $dir = $LocalId->get_dir( $ptcpId ); $fileName = date( 'Ymd-His', $Timestamp ) . '-key-renewal-permission'; $receiptString = $receipt->dump( TRUE ); $FileSystem->put_contents( "{$dir}/{$fileName}", $receiptString ); return $receiptString; } static function handle_participants_data_submission( $message, $receipt ){ global $FileSystem, $LocalId, $Timestamp; $object = [ 'type' => 'server', 'id' => '', 'dir' => '/' ]; if ( ! ptcp_is_authorized( $message->get('From'), 'participants_data_submission', $object ) ){ $receipt->set_rejection( 31, _('Sender is not authorized to submit participants data') ); return $receipt->dump( TRUE ); } $options['delimiter'] = $message->get('Delimiter'); $options['enclosure'] = $message->get('Enclosure'); $options['escape'] = $message->get('Escape'); array_map( NULL, $options ); $result = $LocalId->store_lookup_table( $message->get('Participants-Data'), $message->get('Id-Title'), $options ); if ( is_string( $result ) ){ if ( $result[0] == '!' ){ $receipt->set_failure( substr( $result, 1 ) ); } else { $receipt->set_rejection( 22, "Invalid data ({$result})" ); } return $receipt->dump( TRUE ); } $dir = $LocalId->get_dir(); $fileName = date( 'Ymd-His', $Timestamp ) . '-participants-data-submission'; $receiptString = $receipt->dump( TRUE ); $FileSystem->put_contents( "{$dir}/{$fileName}", $receiptString ); return $receiptString; } } // end of file local_id_messages.class.php