File Coverage

blib/lib/OpenCA/REQ.pm
Criterion Covered Total %
statement 9 344 2.6
branch 0 190 0.0
condition 0 27 0.0
subroutine 3 20 15.0
pod 0 17 0.0
total 12 598 2.0


line stmt bran cond sub pod time code
1             ## OpenCA::REQ
2             ##
3             ## Copyright (C) 1998-1999 Massimiliano Pala (madwolf@openca.org)
4             ## All rights reserved.
5             ##
6             ## This library is free for commercial and non-commercial use as long as
7             ## the following conditions are aheared to. The following conditions
8             ## apply to all code found in this distribution, be it the RC4, RSA,
9             ## lhash, DES, etc., code; not just the SSL code. The documentation
10             ## included with this distribution is covered by the same copyright terms
11             ##
12             ## Copyright remains Massimiliano Pala's, and as such any Copyright notices
13             ## in the code are not to be removed.
14             ## If this package is used in a product, Massimiliano Pala should be given
15             ## attribution as the author of the parts of the library used.
16             ## This can be in the form of a textual message at program startup or
17             ## in documentation (online or textual) provided with the package.
18             ##
19             ## Redistribution and use in source and binary forms, with or without
20             ## modification, are permitted provided that the following conditions
21             ## are met:
22             ## 1. Redistributions of source code must retain the copyright
23             ## notice, this list of conditions and the following disclaimer.
24             ## 2. Redistributions in binary form must reproduce the above copyright
25             ## notice, this list of conditions and the following disclaimer in the
26             ## documentation and/or other materials provided with the distribution.
27             ## 3. All advertising materials mentioning features or use of this software
28             ## must display the following acknowledgement:
29             ## "This product includes OpenCA software written by Massimiliano Pala
30             ## (madwolf@openca.org) and the OpenCA Group (www.openca.org)"
31             ## 4. If you include any Windows specific code (or a derivative thereof) from
32             ## some directory (application code) you must include an acknowledgement:
33             ## "This product includes OpenCA software (www.openca.org)"
34             ##
35             ## THIS SOFTWARE IS PROVIDED BY OPENCA DEVELOPERS ``AS IS'' AND
36             ## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37             ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38             ## ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
39             ## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40             ## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41             ## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42             ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43             ## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44             ## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45             ## SUCH DAMAGE.
46             ##
47             ## The licence and distribution terms for any publically available version or
48             ## derivative of this code cannot be changed. i.e. this code cannot simply be
49             ## copied and put under another distribution licence
50             ## [including the GNU Public Licence.]
51             ##
52              
53             ## moduleerrorcode is 72
54             ##
55             ## functions:
56             ##
57             ## new 11
58             ## init 12
59             ## getParsed 21
60             ## getHeader 31
61             ## getSignature 32
62             ## getKey 33
63             ## getBody 34
64             ## getRawHeader 35
65             ## parseReq 13
66             ## getTXT 41
67             ## getPEM 42
68             ## getDER 43
69             ## getItem 51
70             ## getSerial 52
71             ## setParams 61
72              
73 1     1   720 use strict;
  1         2  
  1         31  
74 1     1   4 use Digest::MD5;
  1         2  
  1         38  
75 1     1   793 use X500::DN;
  1         172487  
  1         6588  
76              
77             package OpenCA::REQ;
78              
79             our ($errno, $errval);
80              
81             ($OpenCA::REQ::VERSION = '$Revision: 1.52 $' )=~ s/(?:^.*: (\d+))|(?:\s+\$$)/defined $1?"0\.9":""/eg;
82              
83             my %params = (
84             req => undef,
85             item => undef,
86             pemREQ => undef,
87             derREQ => undef,
88             txtREQ => undef,
89             spkacREQ => undef,
90             revokeREQ => undef,
91             parsedSPKAC => undef,
92             parsedCRR => undef,
93             parsedItem => undef,
94             backend => undef,
95             beginHeader => undef,
96             endHeader => undef,
97             beginSignature => undef,
98             endSignature => undef,
99             beginKey => undef,
100             endKey => undef,
101             beginAttribute => undef,
102             endAttribute => undef,
103             reqFormat => undef,
104             );
105              
106             sub setError {
107 0     0 0   my $self = shift;
108              
109 0 0         if (scalar (@_) == 4) {
110 0           my $keys = { @_ };
111 0           $errval = $keys->{ERRVAL};
112 0           $errno = $keys->{ERRNO};
113             } else {
114 0           $errno = $_[0];
115 0           $errval = $_[1];
116             }
117              
118             ## support for: return $self->setError (1234, "Something fails.") if (not $xyz);
119 0           return undef;
120             }
121              
122             sub new {
123 0     0 0   my $that = shift;
124 0   0       my $class = ref($that) || $that;
125              
126 0           my $self = {
127             %params,
128             };
129              
130 0           bless $self, $class;
131              
132 0           $self->{beginHeader} = "-----BEGIN HEADER-----";
133 0           $self->{endHeader} = "-----END HEADER-----";
134 0           $self->{beginSignature} = "-----BEGIN PKCS7-----";
135 0           $self->{endSignature} = "-----END PKCS7-----";
136 0           $self->{beginKey} = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
137 0           $self->{endKey} = "-----END ENCRYPTED PRIVATE KEY-----";
138 0           $self->{beginAttribute} = "-----BEGIN ATTRIBUTE-----";
139 0           $self->{endAttribute} = "-----END ATTRIBUTE-----";
140 0           $self->{reqFormat} = "";
141              
142 0           my $keys = { @_ };
143 0           my ( $infile, $keyfile, $tmp );
144              
145 0           $self->{req} = $keys->{DATA};
146 0   0       $self->{reqFormat} = ( $keys->{FORMAT} or $keys->{INFORM} );
147              
148 0           $self->{backend} = $keys->{SHELL};
149 0           $infile = $keys->{INFILE};
150 0           $keyfile = $keys->{KEYFILE};
151            
152 0 0         return $self->setError (7211011, "OpenCA::REQ->new: The backend is not specified.") if (not $self->{backend});
153              
154 0 0         if( $keyfile ) {
155 0 0 0       if ( not defined $self->{reqFormat} or not $self->{reqFormat} ) {
156 0           $self->{reqFormat} = "PEM";
157             }
158 0           $self->{req} = $self->{backend}->genReq( KEYFILE=>$keys->{KEYFILE},
159             DN=>$keys->{DN},
160             SUBJECT=>$keys->{SUBJECT},
161             OUTFORM=>$self->{reqFormat},
162             PASSWD=>$keys->{PASSWD} );
163              
164 0 0         return $self->setError (7211021,
165             "OpenCA::REQ->new: Cannot create new request.\n".
166             "Backend fails with errorcode ".$OpenCA::OpenSSL::errno."\n".
167             $OpenCA::OpenSSL::errval)
168             if ( not $self->{req} );
169             }
170              
171 0 0         if( $infile ) {
172 0           $self->{req} = "";
173              
174 0 0         open(FD, "<$infile" ) or
175             return $self->setError (7211031,
176             "OpenCA::REQ->new: Cannot open infile $infile for reading.");
177 0           while ( $tmp = ) {
178 0           $self->{req} .= $tmp;
179             }
180 0           close(FD);
181              
182 0 0         return $self->setError (7211033, "Cannot read request from infile $infile.")
183             if( not $self->{req});
184             }
185              
186 0 0 0       if( not (defined($self->{reqFormat})) or ($self->{reqFormat} eq "")) {
187 0 0 0       if( ( $self->{req} ) and ( $self->{req} =~ /SPKAC\s*=\s*/g ) ){
    0 0        
188 0           $self->{reqFormat} = "SPKAC";
189             } elsif (($self->{req}) and ($self->{req} =~
190             /REVOKE_CERTIFICATE_SERIAL\s*=\s*/g)){
191 0           $self->{reqFormat} = "CRR";
192             } else {
193 0           $self->{reqFormat} = "PEM";
194             }
195             }
196              
197 0 0         if ( $self->{req} ne "" ) {
198 0           $self->{item} = $self->{req};
199              
200 0 0         if ( not $self->init( REQ=>$self->{req},
201             FORMAT=>$self->{reqFormat})) {
202 0           return $self->setError (7211041,
203             "OpenCA::REQ->new: Cannot initialize request (".$errno.")\n".$errval);
204             }
205              
206             }
207              
208 0           return $self;
209             }
210              
211             sub init {
212 0     0 0   my $self = shift;
213 0           my $keys = { @_ };
214              
215 0           $self->{reqFormat} = $keys->{FORMAT};
216 0           $self->{req} = $self->getBody( REQUEST=> $keys->{REQ});
217              
218 0 0         if (not $self->{req}) {
    0          
219 0           $self->{parsedItem} = $self->parseReq( REQ=>$keys->{REQ},
220             FORMAT=>$self->{reqFormat} );
221 0 0         return $self->setError (7212011, "OpenCA::REQ->init: Cannot parse request ".
222             "($errno):\n$errval")
223             if (not $self->{parsedItem});
224             } elsif( $self->{reqFormat} !~ /SPKAC|CRR/i ) {
225 0           $self->{pemREQ} = "";
226 0           $self->{derREQ} = "";
227 0           $self->{txtREQ} = "";
228              
229 0           $self->{parsedItem} = $self->parseReq( REQ=>$keys->{REQ},
230             FORMAT=>$self->{reqFormat} );
231 0 0         return $self->setError (7212024, "OpenCA::REQ->init: Cannot parse request ".
232             "($errno):\n$errval")
233             if (not $self->{parsedItem});
234             } else {
235              
236 0 0         if ( $self->{reqFormat} =~ /SPKAC/ ) {
    0          
237 0           $self->{spkacREQ} = $self->{req};
238 0           $self->{parsedSPKAC}=$self->parseReq( REQ=>$keys->{REQ},
239             FORMAT=>"SPKAC" );
240 0           $self->{parsedItem} = $self->{parsedSPKAC};
241              
242 0 0         return $self->setError (7212026, "OpenCA::REQ->init: Cannot parse request ".
243             "($errno):\n$errval")
244             if( not $self->{parsedSPKAC} );
245              
246             } elsif ( $self->{reqFormat} =~ /CRR/ ) {
247 0           $self->{revokeREQ} = $self->{req};
248 0           $self->{parsedCRR}=
249             $self->parseReq( REQ=>$keys->{REQ},
250             FORMAT=>"CRR" );
251 0           $self->{parsedItem} = $self->{parsedCRR};
252              
253 0 0         return $self->setError (7212031, "OpenCA::REQ->init: Cannot parse request ".
254             "($errno):\n$errval")
255             if( not $self->{parsedCRR} );
256             } else {
257 0           return $self->setError (7212041, "OpenCA::REQ->init: Unknown request's format.");
258             }
259             }
260              
261 0           return 1;
262             }
263              
264             sub getParsed {
265 0     0 0   my $self = shift;
266              
267 0 0         if( $self->{reqFormat} =~ /SPKAC/i ) {
    0          
268 0 0         return $self->setError (7221011, "OpenCA::REQ->getParsed: SPKAC-request was not parsed.")
269             if( not $self->{parsedSPKAC} );
270 0           return $self->{parsedSPKAC};
271             } elsif( $self->{reqFormat} =~ /CRR/i ) {
272 0 0         return $self->setError (7221013, "OpenCA::REQ->getParsed: CRR was not parsed.")
273             if( not $self->{parsedCRR} );
274 0           return $self->{parsedCRR};
275             } else {
276 0 0         return $self->setError (7221014, "OpenCA::REQ->getParsed: Request was not parsed.")
277             if ( not $self->{parsedItem} );
278 0           return $self->{parsedItem};
279             }
280             }
281              
282             sub getHeader {
283 0     0 0   my $self = shift;
284 0           my $keys = { @_ };
285 0           my $req = $keys->{REQUEST};
286              
287 0           my ( $txt, $ret, $i, $key, $val );
288              
289 0           my $beginHeader = $self->{beginHeader};
290 0           my $endHeader = $self->{endHeader};
291 0           my $beginAttribute = $self->{beginAttribute};
292 0           my $endAttribute = $self->{endAttribute};
293              
294 0 0         if( ($txt) = ( $req =~ /$beginHeader\s*\n([\s\S\n]+)\n$endHeader/) ) {
295 0           my $active_multirow = 0;
296 0           foreach $i ( split ( /\s*\n/, $txt ) ) {
297 0 0         if ($active_multirow) {
    0          
298             ## multirow
299 0 0         if ($i =~ /^$endAttribute$/) {
300             ## end of multirow
301 0           $active_multirow = 0;
302             } else {
303 0 0         $ret->{$key} .= "\n" if ($ret->{$key});
304             ## additional data
305 0           $ret->{$key} .= $i;
306             }
307             } elsif ($i =~ /^$beginAttribute$/) {
308             ## begin of multirow
309 0           $active_multirow = 1;
310             } else {
311             ## no multirow
312             ## if multirow then $ret->{key} is initially empty)
313             ## fix CR
314 0           $i =~ s/\s*\r$//;
315 0           $i =~ s/\s*=\s*/=/;
316 0           ( $key, $val ) = ( $i =~ /^([^=]*)\s*=\s*(.*)\s*/ );
317 0           $ret->{$key} = $val;
318             ## fix old requests
319 0 0         if ($key eq "SUBJ") {
320 0           $ret->{SUBJECT} = $val;
321             }
322             }
323              
324              
325             }
326             }
327              
328 0           return $ret;
329             }
330              
331             sub getRawHeader {
332 0     0 0   my $self = shift;
333 0           my $keys = { @_ };
334 0           my $req = $keys->{REQUEST};
335              
336 0           my $beginHeader = $self->{beginHeader};
337 0           my $endHeader = $self->{endHeader};
338              
339 0           my ( $ret ) = ( $req =~ /($beginHeader[\S\s\n]+$endHeader)/ );
340 0           return $ret;
341             }
342              
343             sub getSignature {
344 0     0 0   my $self = shift;
345 0           my $keys = { @_ };
346 0           my $req = $keys->{REQUEST};
347              
348 0           my $beginSig = $self->{beginSignature};
349 0           my $endSig = $self->{endSignature};
350              
351 0           my ( $ret ) = ( $req =~ /($beginSig[\S\s\n]+$endSig)/ );
352 0           return $ret;
353             }
354              
355             sub getKey {
356 0     0 0   my $self = shift;
357 0           my $keys = { @_ };
358 0           my $req = $keys->{REQUEST};
359              
360 0           my $beginKey = $self->{beginKey};
361 0           my $endKey = $self->{endKey};
362              
363 0           my ( $ret ) = ( $req =~ /($beginKey[\S\s\n]+$endKey)/ );
364 0           return $ret;
365             }
366              
367             sub getBody {
368 0     0 0   my $self = shift;
369 0           my $keys = { @_ };
370              
371 0           my $ret = $keys->{REQUEST};
372 0 0         return $self->{req} if (not $ret);
373              
374 0           my $beginHeader = $self->{beginHeader};
375 0           my $endHeader = $self->{endHeader};
376              
377 0           my $beginSig = $self->{beginSignature};
378 0           my $endSig = $self->{endSignature};
379              
380 0           my $beginKey = $self->{beginKey};
381 0           my $endKey = $self->{endKey};
382              
383             ## Let's throw away text between the two headers, included
384 0           $ret =~ s/($beginHeader[\S\s\n]+$endHeader\n*)//;
385              
386             ## Let's throw away text between the two headers, included
387 0           $ret =~ s/($beginSig[\S\s\n]+$endSig)//;
388              
389             ## Let's throw away text between the two headers, included
390 0           $ret =~ s/($beginKey[\S\s\n]+$endKey)//;
391              
392 0           $ret =~ s/\n$//;
393              
394 0           return $ret;
395             }
396              
397             sub parseReq {
398 0     0 0   my $self = shift;
399 0           my $keys = { @_ };
400              
401 0           my $fullReq = $keys->{REQ};
402 0           my $format = $keys->{FORMAT};
403              
404 0           my @dnList = ();
405 0           my @exts = ();
406              
407 0           my ( $ret, $tmp, $key, $val, $tmpOU, $ra, $textReq );
408              
409 0 0         return $self->setError (7213011, "There is no complete request available.")
410             if (not $fullReq);
411              
412             ## timing test
413            
414             #my $start;
415             #use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
416             #$start = [gettimeofday];
417             #$self->{DEBUG_SPEED} = 1;
418              
419 0           $ret->{SIGNATURE} = $self->getSignature ( REQUEST=>$fullReq );
420 0           $ret->{KEY} = $self->getKey ( REQUEST=>$fullReq );
421 0           $ret->{HEADER} = $self->getHeader ( REQUEST=>$fullReq );
422 0           $ret->{RAWHEADER} = $self->getRawHeader ( REQUEST=>$fullReq );
423 0           $ret->{BODY} = $self->getBody ( REQUEST=> $fullReq);
424 0           $ret->{ITEM} = $self->{item};
425              
426             #print "OpenCA::REQ->parseReq: split_time_1=".tv_interval($start)."
\n"
427             # if ($self->{DEBUG_SPEED});
428              
429 0 0         if (not $ret->{BODY}) {
430             ## this must be a request with TYPE == HEADER
431 0 0         print "OpenCA::REQ->parseReq: This is a HEADER only.
\n" if ($self->{DEBUG});
432              
433 0 0         if ( not $ret->{HEADER} ) {
434 0           return $self->setError (7213015,
435             "OpenCA::REQ->init: The request has no body.");
436             }
437 0 0         if ( not $ret->{HEADER}->{TYPE} =~ /HEADER/i ) {
438 0           return $self->setError (7213016,
439             "OpenCA::REQ->init: The request has no body and has not the type HEADER.");
440             }
441              
442 0           $ret->{TYPE} = "HEADER";
443 0           $ret->{DN} = $ret->{HEADER}->{SUBJECT};
444             } else {
445              
446 0           $textReq = $ret->{BODY};
447              
448 0 0         print "OpenCA::REQ->parseReq: FORMAT: $format
\n" if ($self->{DEBUG});
449              
450             ## if ( $format !~ /CRR/ ) {
451 0 0         if ( uc $format ne "CRR" ) {
452             ## Get Attributes from openssl directly
453 0           my @attrlist;
454 0 0         if ( $format =~ /SPKAC/i ) {
455 0           @attrlist = ( "PUBKEY", "KEYSIZE", "PUBKEY_ALGORITHM", "EXPONENT", "MODULUS",
456             "SIGNATURE_ALGORITHM" );
457             } else {
458 0           @attrlist = ( "DN", "VERSION", "SIGNATURE_ALGORITHM",
459             "PUBKEY", "KEYSIZE", "PUBKEY_ALGORITHM", "EXPONENT", "MODULUS" );
460             }
461             #print "OpenCA::REQ->parseReq: split_time_1_4=".tv_interval($start)."
\n"
462             # if ($self->{DEBUG_SPEED});
463 0           my $attrs = $self->{backend}->getReqAttribute( DATA=>$ret->{BODY}. "\n",
464             ATTRIBUTE_LIST=>\@attrlist, INFORM=>$format );
465             #print "OpenCA::REQ->parseReq: split_time_1_5=".tv_interval($start)."
\n"
466             # if ($self->{DEBUG_SPEED});
467 0           foreach (keys %$attrs ) {
468 0           $ret->{$_} = $attrs->{$_};
469 0 0         if ($self->{DEBUG}) {
470 0           print "OpenCA::REQ->parseReq: ATTRIBUTE: ".$_."
\n";
471 0           print "OpenCA::REQ->parseReq: VALUE: ".$ret->{$_}."
\n";
472             }
473             }
474             }
475              
476 0 0         if( exists $ret->{PUBKEY} ) {
477 0           my $md5 = new Digest::MD5;
478 0           $md5->add( $ret->{PUBKEY} );
479 0           $ret->{KEY_DIGEST} = $md5->hexdigest();
480             }
481              
482 0 0         if ( $format =~ /SPKAC/i ) {
    0          
483             ## Specific for SPKAC requests...
484 0           my ( @reqLines );
485              
486 0           @reqLines = split( /\n/ , $textReq );
487 0           for $tmp (@reqLines) {
488              
489 0           $tmp =~ s/\r$//;
490              
491 0           my ($key,$val)=($tmp =~ /([\w]+)\s*=\s*(.*)\s*/ );
492             ## this is a bug at minimum for emailAddress
493             ## $key = uc( $key );
494              
495 0 0         if ($key ne "") {
496 0 0         if ($key =~ /SPKAC/i) {
497 0           $ret->{SPKAC} = $val;
498             } else {
499 0 0         $ret->{DN} .= ", " if ($ret->{DN});
500 0           $ret->{DN} .= $key."=".$val;
501             }
502             }
503              
504             }
505              
506             ## Now retrieve the SPKAC crypto infos...
507 0           $textReq=$self->{backend}->SPKAC( SPKAC=>$textReq);
508              
509 0           $ret->{VERSION} = 1;
510 0           $ret->{TYPE} = 'SPKAC';
511             } elsif( $format =~ /CRR/i ) {
512             ## Specific for CRRs...
513 0           my ( @reqLines );
514              
515 0           @reqLines = split( /\n/ , $textReq );
516 0           for $tmp (@reqLines) {
517              
518 0           $tmp =~ s/\r$//;
519              
520 0           ($key,$val)=($tmp =~ /([\w]+)\s*=\s*(.*)\s*/ );
521 0           $key = uc( $key );
522              
523 0           $ret->{$key} = $val;
524             }
525              
526 0 0         $ret->{VERSION} = 1 if ( not exists $ret->{VERSION});
527              
528 0           $ret->{TYPE} = 'CRR';
529 0           $ret->{HEADER}->{TYPE} = $ret->{TYPE};
530              
531 0           $ret->{REVOKE_CERTIFICATE_DN} =~ s/^\///;
532 0           $ret->{REVOKE_CERTIFICATE_DN} =~ s/\/([A-Za-z0-9\-]+)=/, $1=/g;
533              
534             ## allow automatic parsing
535 0           $ret->{DN} = $ret->{REVOKE_CERTIFICATE_DN};
536              
537 0           $ret->{REASON} = $ret->{REVOKE_REASON};
538 0           $ret->{REVOKE_REASON} = $ret->{REVOKE_REASON};
539             } else {
540 0           $ret->{DN} =~ s/\,\s*$//;
541 0 0         if( exists $ret->{HEADER}->{TYPE} ) {
542 0           $ret->{TYPE} = $ret->{HEADER}->{TYPE};
543             } else {
544 0           $ret->{TYPE} = 'PKCS#10';
545             }
546             }
547             }
548              
549             #print "OpenCA::REQ->parseReq: split_time_2=".tv_interval($start)."
\n"
550             # if ($self->{DEBUG_SPEED});
551              
552             ## load the differnt parts of the DN into DN_HASH
553 0           my $fixed_dn;
554             my $rdn;
555 0 0         if ($ret->{HEADER}->{SUBJECT}) {
556 0 0         print "OpenCA::REQ->parseReq: SUBJECT: ".$ret->{HEADER}->{SUBJECT}."
\n" if ($self->{DEBUG});
557 0           $fixed_dn = $ret->{HEADER}->{SUBJECT};
558             } else {
559 0 0         print "OpenCA::REQ->parseReq: DN: ".$ret->{DN}."
\n" if ($self->{DEBUG});
560 0           $fixed_dn = $ret->{DN};
561             }
562              
563             ## OpenSSL includes a bug in -nameopt RFC2253
564             ## = signs are not escaped if they are normal values
565 0           my $i = 0;
566 0           my $now = "name";
567 0           while ($i < length ($fixed_dn))
568             {
569 0 0         if (substr ($fixed_dn, $i, 1) eq '\\')
    0          
    0          
570             {
571 0           $i++;
572             } elsif (substr ($fixed_dn, $i, 1) eq '=') {
573 0 0         if ($now =~ /value/)
574             {
575             ## OpenSSL forgets to escape =
576 0           $fixed_dn = substr ($fixed_dn, 0, $i)."\\".substr ($fixed_dn, $i);
577 0           $i++;
578             } else {
579 0           $now = "value";
580             }
581             } elsif (substr ($fixed_dn, $i, 1) =~ /[,+]/) {
582 0           $now = "name";
583             }
584 0           $i++;
585             }
586              
587             #print "OpenCA::REQ->parseReq: split_time_3=".tv_interval($start)."
\n"
588             # if ($self->{DEBUG_SPEED});
589              
590 0 0         if ($fixed_dn =~ /[\\+]/) {
591 0           my $x500_dn = X500::DN->ParseRFC2253 ($fixed_dn);
592 0           foreach $rdn ($x500_dn->getRDNs()) {
593 0 0         next if ($rdn->isMultivalued());
594 0           my @attr_types = $rdn->getAttributeTypes();
595 0           my $type = $attr_types[0];
596 0           my $value = $rdn->getAttributeValue ($type);
597 0           push (@{$ret->{DN_HASH}->{uc($type)}}, $value);
  0            
598 0 0         print "OpenCA::REQ->parseReq: DN_HASH: $type=$value
\n" if ($self->{DEBUG});
599             }
600             } else {
601 0           my @rdns = split /,/, $fixed_dn;
602 0           foreach $rdn (@rdns) {
603 0           my ($type, $value) = split /=/, $rdn;
604 0           $type =~ s/^\s*//;
605 0           $type =~ s/\s*$//;
606 0           $value =~ s/^\s*//;
607 0           $value =~ s/\s*$//;
608 0           push (@{$ret->{DN_HASH}->{uc($type)}}, $value);
  0            
609 0 0         print "OpenCA::REQ->parseReq: DN_HASH: $type=$value
\n" if ($self->{DEBUG});
610             }
611             }
612              
613             #print "OpenCA::REQ->parseReq: split_time_4=".tv_interval($start)."
\n"
614             # if ($self->{DEBUG_SPEED});
615              
616             ## show DN to check conformance to RFC 2253
617 0 0         if ($self->{DEBUG}) {
618 0           print "OpenCA::REQ->parseReq: TYPE: ".$ret->{TYPE}."
\n";
619 0           print "OpenCA::REQ->parseReq: DN: ".$ret->{DN}."
\n";
620             }
621              
622             ## set emailaddress
623             ## FIXME: actually we ignore the subject alternative name in the header
624             ## FIXME: this is a BUG
625 0 0 0       if ($ret->{HEADER}->{SUBJECT_ALT_NAME} and
    0 0        
      0        
626             ( ($ret->{HEADER}->{SUBJECT_ALT_NAME} =~ /^\s*email\s*:/i) or
627             ($ret->{HEADER}->{SUBJECT_ALT_NAME} =~ /,\s*email\s*:/i) ) ) {
628 0           ( $ret->{EMAILADDRESS} ) =
629             ( $ret->{HEADER}->{SUBJECT_ALT_NAME} =~
630             /^\s*email\s*:\s*([^,]*),?/ );
631 0 0         if (not $ret->{EMAILADDRESS}) {
632 0           ( $ret->{EMAILADDRESS} ) =
633             ( $ret->{HEADER}->{SUBJECT_ALT_NAME} =~
634             /,\s*email\s*:\s*([^,]*),?/ );
635             }
636             } elsif (
637             ##$ret->{HEADER}->{SUBJECT} and
638             $ret->{DN_HASH}->{EMAILADDRESS} and
639             $ret->{DN_HASH}->{EMAILADDRESS}[0]) {
640 0           $ret->{EMAILADDRESS} = $ret->{DN_HASH}->{EMAILADDRESS}[0];
641             ##} else {
642             ## $ret->{EMAILADDRESS} = $ret->{DN_HASH}->{EMAILADDRESS}[0];
643             }
644 0 0         if ($self->{DEBUG}) {
645 0           print "OpenCA::REQ->parseReq: SUBJECT_ALT_NAME: ".$ret->{HEADER}->{SUBJECT_ALT_NAME}."
\n";
646 0           print "OpenCA::REQ->parseReq: EMAILADDRESS: ".$ret->{EMAILADDRESS}."
\n";
647             }
648              
649 0 0         if ($ret->{HEADER}->{TYPE} !~ /HEADER/) {
650             ## Common Request Parsing ...
651 0           $ret->{PK_ALGORITHM} = $ret->{PUBKEY_ALGORITHM};
652 0           $ret->{SIG_ALGORITHM} = $ret->{SIGNATURE_ALGORITHM};
653 0 0         $ret->{TYPE} .= " with PKCS#7 Signature" if ( $ret->{SIGNATURE} );
654             }
655              
656             ## timing test
657              
658             #if ($self->{DEBUG_SPEED})
659             #{
660             # print "OpenCA::REQ->parseReq: split_time_last=".tv_interval($start)."
\n";
661             # $errno += tv_interval ( $start );
662             # print "OpenCA::REQ->parseReq: total_time=".$errno."
\n";
663             #}
664              
665 0           return $ret;
666             }
667              
668             sub getTXT {
669 0     0 0   my $self = shift;
670 0           my $ret;
671              
672 0 0         if( $self->{reqFormat} =~ /SPKAC/i ) {
    0          
673 0 0         return $self->setError (7241011, "OpenCA::REQ->getTXT: The request should be in SPKAC-format ".
674             "but there is no SPKAC-request.")
675             if( not $self->{spkacREQ} );
676              
677 0           $ret = $self->{req} .
678             $self->{backend}->SPKAC( SPKAC => $self->{spkacREQ} );
679 0           return $ret;
680             } elsif( $self->{reqFormat} =~ /CRR/i ) {
681 0 0         return $self->setError (7241013, "OpenCA::REQ->getTXT: The request should be a CRR ".
682             "but there is no such request.")
683             if( not $self->{revokeREQ} );
684              
685 0           $ret = $self->{req};
686 0           return $ret;
687             } else {
688 0 0         if (not $self->{txtREQ}) {
689 0           $self->{txtREQ} = $self->{backend}->dataConvert(
690             DATA=>$self->{req},
691             DATATYPE=>"REQUEST",
692             INFORM=>$self->{reqFormat},
693             OUTFORM=>"TXT" );
694 0 0         return $self->setError (7241021, "OpenCA::REQ->init: Cannot convert request to TXT-format ".
695             "(".$OpenCA::OpenSSL::errno."):\n".
696             $OpenCA::OpenSSL::errval)
697             if (not $self->{txtREQ});
698             }
699              
700 0 0         return $self->setError (7241015, "OpenCA::REQ->getTXT: The request should be a TXT-request ".
701             "but there is no TXT-request.")
702             if ( not $self->{txtREQ} );
703 0           return $self->{txtREQ};
704             }
705             }
706              
707             sub getPEM {
708 0     0 0   my $self = shift;
709 0           my $ret;
710              
711 0 0         return $self->setError (7242011, "OpenCA::REQ->getPEM: The request is in SPKAC-format and not in PEM-format.")
712             if( $self->{reqFormat} =~ /SPKAC/i );
713 0 0         return $self->setError (7242013, "OpenCA::REQ->getPEM: The request is a CRR.")
714             if( $self->{reqFormat} =~ /CRR/i );
715              
716 0 0         if ( $self->{reqFormat} eq 'PEM' ) {
717 0 0         $self->{req} .= "\n" if ($self->{req} !~ /\n$/);
718 0           return $self->{req};
719             }
720 0 0         if (not $self->{pemREQ}) {
721 0           $self->{pemREQ} = $self->{backend}->dataConvert(
722             DATA=>$self->{req},
723             DATATYPE=>"REQUEST",
724             INFORM=>$self->{reqFormat},
725             OUTFORM=>"PEM" );
726 0 0         return $self->setError (7242021, "OpenCA::REQ->getPEM: Cannot convert request to PEM-format ".
727             "(".$OpenCA::OpenSSL::errno."):\n".
728             $OpenCA::OpenSSL::errval)
729             if (not $self->{pemREQ});
730             }
731              
732 0 0         return $self->setError (7242015, "OpenCA::REQ->getPEM: The request is not available in PEM-format.")
733             if ( not $self->{pemREQ} );
734              
735 0           return $self->{pemREQ};
736             }
737              
738             sub getDER {
739 0     0 0   my $self = shift;
740 0           my $ret;
741              
742 0 0         return $self->setError (7243011, "OpenCA::REQ->getDER: The request is in SPKAC-format and not in DER-format.")
743             if( $self->{reqFormat} =~ /SPKAC/i );
744 0 0         return $self->setError (7243013, "OpenCA::REQ->getDER: The request is a CRR.")
745             if( $self->{reqFormat} =~ /CRR/i );
746              
747 0 0         if ( $self->{reqFormat} eq 'DER' ) {
748 0           return $self->{req};
749             }
750 0 0         if (not $self->{derREQ}) {
751 0           $self->{derREQ} = $self->{backend}->dataConvert(
752             DATA=>$self->{req},
753             DATATYPE=>"REQUEST",
754             INFORM=>$self->{reqFormat},
755             OUTFORM=>"DER" );
756 0 0         return $self->setError (7243021, "OpenCA::REQ->getDER: Cannot convert request to DER-format ".
757             "(".$OpenCA::OpenSSL::errno."):\n".
758             $OpenCA::OpenSSL::errval)
759             if (not $self->{derREQ});
760             }
761              
762 0 0         return $self->setError (7243015, "OpenCA::REQ->getDER: The request is not available in DER-format.")
763             if ( not $self->{derREQ} );
764              
765 0           return $self->{derREQ};
766             }
767              
768             sub getItem {
769 0     0 0   my $self = shift;
770              
771 0           return $self->getParsed()->{ITEM};
772             }
773              
774             sub getSerial {
775 0     0 0   my $self = shift;
776              
777 0           my $ret = $self->getParsed()->{HEADER}->{SERIAL};
778 0 0         if (not defined $ret) {
779             ## old requests
780 0           $ret = $self->getParsed()->{SERIAL};
781             }
782              
783 0           return $ret;
784             }
785              
786             sub setParams {
787              
788 0     0 0   my $self = shift;
789 0           my $params = { @_ };
790 0           my $key;
791              
792 0           foreach $key ( keys %{$params} ) {
  0            
793             ## we should place the parameters here
794             }
795              
796 0           return 1;
797             }
798              
799             ## by michael bell to support signature in the header
800             ## 1) works actually only with PEM because automatical
801             ## transformation to DER etc. is a high risc
802             ## for a failure
803             ## 2) please submit only one attribute
804             sub setHeaderAttribute {
805              
806 0     0 0   my $self = shift;
807 0           my $keys = { @_ };
808              
809 0           my $beginHeader = $self->{beginHeader};
810 0           my $endHeader = $self->{endHeader};
811 0           my $beginAttribute = $self->{beginAttribute};
812 0           my $endAttribute = $self->{endAttribute};
813              
814             ## check format to be PEM
815 0 0         return $self->setError (7251011, "OpenCA::REQ->setHeaderAttribute: The request is not in PEM-format.")
816             if ($self->{reqFormat} !~ /^PEM|CRR|SPKAC$/i);
817 0 0         print "REQ->setHeaderAttribute: correct format - PEM
\n" if ($self->{DEBUG});
818              
819             ## check for header
820 0 0         if ($self->{item} !~ /$beginHeader/) {
821             ## create header
822 0           $self->{item} = $beginHeader."\n".$endHeader."\n".$self->{item};
823             }
824              
825 0           for my $attribute (keys %{$keys}) {
  0            
826              
827 0 0         print "REQ->setHeaderAttribute: $attribute:=".$keys->{$attribute}."
\n" if ($self->{DEBUG});
828              
829             ## insert into item
830             ## find last position in header
831             ## enter attributename
832             ## check fo multirow
833 0 0         if ($keys->{$attribute} =~ /\n/) {
834             ## multirow
835 0           $self->{item} =~ s/${endHeader}/${attribute}=\n${beginAttribute}\n$keys->{$attribute}\n${endAttribute}\n${endHeader}/;
836             } else {
837             ## single row
838 0           $self->{item} =~ s/${endHeader}/${attribute}=$keys->{$attribute}\n${endHeader}/;
839             }
840              
841             }
842              
843             ## if you call init then all information is lost !!!
844 0 0         return $self->setError (7251021, "OpenCA::REQ->setHeaderAttribute: Cannot re-initialize the request ".
845             "($errno)\n$errval")
846             if (not $self->init ( REQ => $self->{item},
847             FORMAT => $self->{reqFormat}));
848              
849 0           return 1;
850             }
851              
852             # Autoload methods go after =cut, and are processed by the autosplit program.
853              
854             1;
855             __END__