1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16:
17: require_once("XMLDocument.php");
18:
19: 20: 21: 22: 23: 24:
25: class iSchedule
26: {
27: public $parsed;
28: public $selector;
29: public $domain;
30: private $dk;
31: private $DKSig;
32: private $try_anyway = false;
33: private $failed = false;
34: private $failOnError = true;
35: private $subdomainsOK = true;
36: private $remote_public_key ;
37: private = Array ( 'host',
38: 'originator',
39: 'recipient',
40: 'content-type' );
41: private = Array ( 'connection',
42: 'keep-alive',
43: 'dkim-signature',
44: 'proxy-authenticate',
45: 'proxy-authorization',
46: 'te',
47: 'trailers',
48: 'transfer-encoding',
49: 'upgrade' );
50:
51: function __construct ( )
52: {
53: global $c;
54: $this->selector = 'cal';
55: if ( is_object ( $c ) && isset ( $c->scheduling_dkim_selector ) )
56: {
57: $this->scheduling_dkim_domain = $c->scheduling_dkim_domain ;
58: $this->scheduling_dkim_selector = $c->scheduling_dkim_selector ;
59: $this->schedule_private_key = $c->schedule_private_key ;
60: if ( ! preg_match ( '/BEGIN RSA PRIVATE KEY/', $this->schedule_private_key ) )
61: {
62: $key = file_get_contents ( $this->schedule_private_key );
63: if ( $key !== false )
64: $this->schedule_private_key = $key;
65: }
66: if ( isset ( $c->scheduling_dkim_algo ) )
67: $this->scheduling_dkim_algo = $c->scheduling_dkim_algo;
68: else
69: $this->scheduling_dkim_algo = 'sha256';
70: if ( isset ( $c->scheduling_dkim_valid_time ) )
71: $this->valid_time = $c->scheduling_dkim_valid_time;
72: }
73: }
74:
75: 76: 77:
78: function getTxt ()
79: {
80: global $icfg;
81:
82: if ( $icfg [ $this->remote_selector . '._domainkey.' . $this->remote_server ] )
83: {
84: $this->dk = $icfg [ $this->remote_selector . '._domainkey.' . $this->remote_server ];
85: return true;
86: }
87:
88: $dkim = dns_get_record ( $this->remote_selector . '._domainkey.' . $this->remote_server , DNS_TXT );
89: if ( count ( $dkim ) > 0 )
90: {
91: $this->dk = $dkim [ 0 ] [ 'txt' ];
92: if ( $dkim [ 0 ] [ 'entries' ] )
93: {
94: $this->dk = '';
95: foreach ( $dkim [ 0 ] [ 'entries' ] as $v )
96: {
97: $this->dk .= trim ( $v );
98: }
99: }
100: dbg_error_log( 'ischedule', 'getTxt '. $this->dk . ' XX');
101: }
102: else
103: {
104: dbg_error_log( 'ischedule', 'getTxt FAILED '. print_r ( $dkim ) );
105: $this->failed = true;
106: return false;
107: }
108: return true;
109: }
110:
111: 112: 113:
114: function setTxt ( $dk )
115: {
116: $this->dk = $dk;
117: }
118:
119: 120: 121:
122: function parseTxt ( )
123: {
124: if ( $this->failed == true )
125: return false;
126: $clean = preg_replace ( '/\s?([;=])\s?/', '$1', $this->dk );
127: $pairs = preg_split ( '/;/', $clean );
128: $this->parsed = array();
129: foreach ( $pairs as $v )
130: {
131: list($key,$value) = preg_split ( '/=/', $v, 2 );
132: $value = trim ( $value, '\\' );
133: if ( preg_match ( '/(g|k|n|p|s|t|v)/', $key ) )
134: $this->parsed [ $key ] = $value;
135: else
136: $this->parsed_ignored [ $key ] = $value;
137: }
138: return true;
139: }
140:
141: 142: 143:
144: function validateKey ( )
145: {
146: $this->failed = true;
147: if ( isset ( $this->parsed [ 's' ] ) )
148: {
149: if ( ! preg_match ( '/(\*|calendar)/', $this->parsed [ 's' ] ) ) {
150: dbg_error_log( 'ischedule', 'validateKey ERROR: bad selector' );
151: return false;
152: }
153: }
154: if ( isset ( $this->parsed [ 'k' ] ) && $this->parsed [ 'k' ] != 'rsa' ) {
155: dbg_error_log( 'ischedule', 'validateKey ERROR: bad key algorythm, algo was:' . $this->parsed [ 'k' ] );
156: return false;
157: }
158: if ( isset ( $this->parsed [ 't' ] ) && ! preg_match ( '/^[y:s]+$/', $this->parsed [ 't' ] ) ) {
159: dbg_error_log( 'ischedule', 'validateKey ERROR: type mismatch' );
160: return false;
161: }
162: else
163: {
164: if ( preg_match ( '/y/', $this->parsed [ 't' ] ) )
165: $this->failOnError = false;
166: if ( preg_match ( '/s/', $this->parsed [ 't' ] ) )
167: $this->subdomainsOK = false;
168: }
169: if ( isset ( $this->parsed [ 'g' ] ) )
170: $this->remote_user_rule = $this->parsed [ 'g' ];
171: else
172: $this->remote_user_rule = '*';
173: if ( isset ( $this->parsed [ 'p' ] ) )
174: {
175: if ( preg_match ( '/[^A-Za-z0-9_=+\/]/', $this->parsed [ 'p' ] ) )
176: return false;
177: $data = "-----BEGIN PUBLIC KEY-----\n" . implode ("\n",str_split ( $this->parsed [ 'p' ], 64 )) . "\n-----END PUBLIC KEY-----";
178: if ( $data === false )
179: return false;
180: $this->remote_public_key = $data;
181: }
182: else {
183: dbg_error_log( 'ischedule', 'validateKey ERROR: no key in dns record' . $this->parsed [ 'p' ] );
184: return false;
185: }
186: $this->failed = false;
187: return true;
188: }
189:
190: 191: 192:
193: function getServer ( )
194: {
195: global $icfg;
196: if ( $icfg [ $this->domain ] )
197: {
198: $this->remote_server = $icfg [ $this->domain ] [ 'server' ];
199: $this->remote_port = $icfg [ $this->domain ] [ 'port' ];
200: $this->remote_ssl = $icfg [ $this->domain ] [ 'ssl' ];
201: return true;
202: }
203: $this->remote_ssl = false;
204: $parts = explode ( '.', $this->domain );
205: $tld = $parts [ count ( $parts ) - 1 ];
206: $len = 2;
207: if ( strlen ( $tld ) == 2 && in_array ( $tld, Array ( 'uk', 'nz' ) ) )
208: $len = 3;
209: if ( $this->domain == 'mycaldav' || $this->domain == 'altcaldav' )
210: $len = 1;
211: while ( count ( $parts ) >= $len )
212: {
213: $r = dns_get_record ( '_ischedules._tcp.' . implode ( '.', $parts ) , DNS_SRV );
214: if ( 0 < count ( $r ) )
215: {
216: $remote_server = $r [ 0 ] [ 'target' ];
217: $remote_port = $r [ 0 ] [ 'port' ];
218: $this->remote_ssl = true;
219: break;
220: }
221: if ( ! isset ( $remote_server ) )
222: {
223: $r = dns_get_record ( '_ischedule._tcp.' . implode ( '.', $parts ) , DNS_SRV );
224: if ( 0 < count ( $r ) )
225: {
226: $remote_server = $r [ 0 ] [ 'target' ];
227: $remote_port = $r [ 0 ] [ 'port' ];
228: break;
229: }
230: }
231: array_shift ( $parts );
232: }
233: if ( ! isset ( $remote_server ) )
234: {
235: if ( $this->try_anyway == true )
236: {
237: if ( ! isset ( $remote_server ) )
238: $remote_server = $this->domain;
239: if ( ! isset ( $remote_port ) )
240: $remote_port = 80;
241: }
242: else {
243: dbg_error_log('ischedule', 'Domain %s did not have srv records for iSchedule', $this->domain );
244: return false;
245: }
246: }
247: dbg_error_log('ischedule', $this->domain . ' found srv records for ' . $remote_server . ':' . $remote_port );
248: $this->remote_server = $remote_server;
249: $this->remote_port = $remote_port;
250: return true;
251: }
252:
253: 254: 255:
256: function getCapabilities ( $domain = null )
257: {
258: if ( $domain != null && $this->domain != $domain )
259: $this->domain = $domain;
260: if ( ! isset ( $this->remote_server ) && isset ( $this->domain ) && ! $this->getServer ( ) )
261: return false;
262: $this->remote_url = 'http'. ( $this->remote_ssl ? 's' : '' ) . '://' .
263: $this->remote_server . ':' . $this->remote_port . '/.well-known/ischedule';
264: $remote_capabilities = file_get_contents ( $this->remote_url . '?query=capabilities' );
265: if ( $remote_capabilities === false )
266: return false;
267: $xml_parser = xml_parser_create_ns('UTF-8');
268: $this->xml_tags = array();
269: xml_parser_set_option ( $xml_parser, XML_OPTION_SKIP_WHITE, 1 );
270: xml_parser_set_option ( $xml_parser, XML_OPTION_CASE_FOLDING, 0 );
271: $rc = xml_parse_into_struct( $xml_parser, $remote_capabilities, $this->xml_tags );
272: if ( $rc == false ) {
273: dbg_error_log( 'ERROR', 'XML parsing error: %s at line %d, column %d',
274: xml_error_string(xml_get_error_code($xml_parser)),
275: xml_get_current_line_number($xml_parser), xml_get_current_column_number($xml_parser) );
276: dbg_error_log('ischedule', $this->domain . ' iSchedule error parsing remote xml' );
277: return false;
278: }
279: xml_parser_free($xml_parser);
280: $xmltree = BuildXMLTree( $this->xml_tags );
281: if ( !is_object($xmltree) ) {
282: dbg_error_log('ischedule', $this->domain . ' iSchedule error in remote xml' );
283: $request->DoResponse( 406, translate("REPORT body is not valid XML data!") );
284: return false;
285: }
286: dbg_error_log('ischedule', $this->domain . ' got capabilites' );
287: $this->capabilities_xml = $xmltree;
288: return true;
289: }
290:
291: 292: 293:
294: function queryCapabilities ( $capability, $domain = null )
295: {
296: if ( ! isset ( $this->capabilities_xml ) )
297: {
298: dbg_error_log('ischedule', $this->domain . ' capabilities not set, quering for capability:' . $capability );
299: if ( $domain == null )
300: return false;
301: if ( $this->domain != $domain )
302: $this->domain = $domain;
303: if ( ! $this->getCapabilities ( ) )
304: return false;
305: }
306: switch ( $capability )
307: {
308: case 'VEVENT':
309: case 'VFREEBUSY':
310: case 'VTODO':
311: $comp = $this->capabilities_xml->GetPath ( 'urn:ietf:params:xml:ns:ischedule:supported-scheduling-message-set/urn:ietf:params:xml:ns:ischedule:comp' );
312: foreach ( $comp as $c )
313: {
314: if ( $c->GetAttribute ( 'name' ) == $capability )
315: return true;
316: }
317: return false;
318: case 'VFREEBUSY/REQUEST':
319: case 'VTODO/ADD':
320: case 'VTODO/REQUEST':
321: case 'VTODO/REPLY':
322: case 'VTODO/CANCEL':
323: case 'VEVENT/ADD':
324: case 'VEVENT/REQUEST':
325: case 'VEVENT/REPLY':
326: case 'VEVENT/CANCEL':
327: case 'VEVENT/PUBLISH':
328: case 'VEVENT/COUNTER':
329: case 'VEVENT/DECLINECOUNTER':
330: dbg_error_log('ischedule', $this->domain . ' xml query' );
331: $comp = $this->capabilities_xml->GetPath ( 'urn:ietf:params:xml:ns:ischedule:supported-scheduling-message-set/urn:ietf:params:xml:ns:ischedule:comp' );
332: list ( $component, $method ) = explode ( '/', $capability );
333: dbg_error_log('ischedule', $this->domain . ' quering for capability:' . count ( $comp ) . ' ' . $component );
334: foreach ( $comp as $c )
335: {
336: dbg_error_log('ischedule', $this->domain . ' quering for capability:' . $c->GetAttribute ( 'name' ) . ' == ' . $component );
337: if ( $c->GetAttribute ( 'name' ) == $component )
338: {
339: $methods = $c->GetElements ( 'urn:ietf:params:xml:ns:ischedule:method' );
340: if ( count ( $methods ) == 0 )
341: return true;
342: foreach ( $methods as $m )
343: {
344: if ( $m->GetAttribute ( 'name' ) == $method )
345: return true;
346: }
347: }
348: }
349: return false;
350: default:
351: return false;
352: }
353: }
354:
355: 356: 357: 358: 359: 360:
361: function signDKIM ( $headers, $body )
362: {
363: if ( $this->scheduling_dkim_domain == null )
364: return false;
365: $b = '';
366: if ( is_array ( $headers ) !== true )
367: return false;
368: foreach ( $headers as $key => $value )
369: {
370: $b .= $key . ': ' . $value . "\r\n";
371: }
372: $dk['v'] = '1';
373: $dk['a'] = 'rsa-' . $this->scheduling_dkim_algo;
374: $dk['s'] = $this->selector;
375: $dk['d'] = $this->scheduling_dkim_domain;
376: $dk['c'] = 'simple-http';
377: if ( isset ( $_SERVER['SERVER_NAME'] ) && strstr ( $_SERVER['SERVER_NAME'], $this->domain ) !== false )
378: $dk['i'] = '@' . $_SERVER['SERVER_NAME'];
379: $dk['q'] = 'dns/txt';
380: $dk['l'] = strlen ( $body );
381: $dk['t'] = time ( );
382: if ( isset ( $this->valid_time ) )
383: $dk['x'] = $this->valid_time;
384: $dk['h'] = implode ( ':', array_keys ( $headers ) );
385: $dk['bh'] = base64_encode ( hash ( 'sha256', $body , true ) );
386: $value = '';
387: foreach ( $dk as $key => $val )
388: $value .= "$key=$val; ";
389: $value .= 'b=';
390: $tosign = $b . 'DKIM-Signature: ' . $value;
391: openssl_sign ( $tosign, $sig, $this->schedule_private_key, $this->scheduling_dkim_algo );
392: $this->tosign = $tosign;
393: $value .= base64_encode ( $sig );
394: return $value;
395: }
396:
397: 398: 399: 400: 401: 402:
403: function sendRequest ( $address, $type, $data )
404: {
405: global $session;
406: if ( empty($this->scheduling_dkim_domain) )
407: return false;
408: if ( is_array ( $address ) )
409: list ( $user, $domain ) = explode ( '@', $address[0] );
410: else
411: list ( $user, $domain ) = explode ( '@', $address );
412: if ( ! $this->getCapabilities ( $domain ) )
413: {
414: dbg_error_log('ischedule', $domain . ' did not have iSchedule capabilities for ' . $type );
415: return false;
416: }
417: dbg_error_log('ischedule', $domain . ' trying with iSchedule capabilities for ' . $type );
418: if ( $this->queryCapabilities ( $type ) )
419: {
420: dbg_error_log('ischedule', $domain . ' trying with iSchedule capabilities for ' . $type . ' OK');
421: list ( $component, $method ) = explode ( '/', $type );
422: $headers = array ( );
423: $headers['iSchedule-Version'] = '1.0';
424: $headers['Originator'] = 'mailto:' . $session->email;
425: if ( is_array ( $address ) )
426: $headers['Recipient'] = implode ( ', ' , $address );
427: else
428: $headers['Recipient'] = $address;
429: $headers['Content-Type'] = 'text/calendar; component=' . $component ;
430: if ( $method )
431: $headers['Content-Type'] .= '; method=' . $method;
432: $headers['DKIM-Signature'] = $this->signDKIM ( $headers, $body );
433: if ( $headers['DKIM-Signature'] == false )
434: return false;
435: $request_headers = array ( );
436: foreach ( $headers as $k => $v )
437: $request_headers[] = $k . ': ' . $v;
438: $curl = curl_init ( $this->remote_url );
439: curl_setopt ( $curl, CURLOPT_RETURNTRANSFER, true );
440: curl_setopt ( $curl, CURLOPT_HTTPHEADER, array() );
441: curl_setopt ( $curl, CURLOPT_HTTPHEADER, $request_headers );
442: curl_setopt ( $curl, CURLOPT_SSL_VERIFYPEER, false);
443: curl_setopt ( $curl, CURLOPT_SSL_VERIFYHOST, false);
444: curl_setopt ( $curl, CURLOPT_POST, 1);
445: curl_setopt ( $curl, CURLOPT_POSTFIELDS, $data);
446: curl_setopt ( $curl, CURLOPT_CUSTOMREQUEST, 'POST' );
447: $xmlresponse = curl_exec ( $curl );
448: $info = curl_getinfo ( $curl );
449: curl_close ( $curl );
450: if ( $info['http_code'] >= 400 )
451: {
452: dbg_error_log ( 'ischedule', 'remote server returned error (%s)', $info['http_code'] );
453: return false;
454: }
455:
456: error_log ( 'remote response '. $xmlresponse . print_r ( $info, true ) );
457: $xml_parser = xml_parser_create_ns('UTF-8');
458: $xml_tags = array();
459: xml_parser_set_option ( $xml_parser, XML_OPTION_SKIP_WHITE, 1 );
460: xml_parser_set_option ( $xml_parser, XML_OPTION_CASE_FOLDING, 0 );
461: $rc = xml_parse_into_struct( $xml_parser, $xmlresponse, $xml_tags );
462: if ( $rc == false ) {
463: dbg_error_log( 'ERROR', 'XML parsing error: %s at line %d, column %d',
464: xml_error_string(xml_get_error_code($xml_parser)),
465: xml_get_current_line_number($xml_parser), xml_get_current_column_number($xml_parser) );
466: return false;
467: }
468: $xmltree = BuildXMLTree( $xml_tags );
469: xml_parser_free($xml_parser);
470: if ( !is_object($xmltree) ) {
471: dbg_error_log( 'ERROR', 'iSchedule RESPONSE body is not valid XML data!' );
472: return false;
473: }
474: $resp = $xmltree->GetPath ( '/*/urn:ietf:params:xml:ns:ischedule:response' );
475: $result = array();
476: foreach ( $resp as $r )
477: {
478: $recipient = $r->GetElements ( 'urn:ietf:params:xml:ns:ischedule:recipient' );
479: $status = $r->GetElements ( 'urn:ietf:params:xml:ns:ischedule:request-status' );
480: $calendardata = $r->GetElements ( 'urn:ietf:params:xml:ns:ischedule:calendar-data' );
481: if ( count ( $recipient ) < 1 )
482: continue;
483: if ( count ( $calendardata ) > 0 )
484: {
485: $result [ $recipient[0]->GetContent() ] = $calendardata[0]->GetContent();
486: }
487: else
488: {
489: $result [ $recipient[0]->GetContent() ] = $status[0]->GetContent();
490: }
491: }
492: if ( count ( $result ) < 1 )
493: return false;
494: else
495: return $result;
496: }
497: else
498: return false;
499: }
500:
501: 502: 503: 504: 505:
506: function parseDKIM ( $sig )
507: {
508:
509: $this->failed = true;
510: $tags = preg_split ( '/;[\s\t]/', $sig );
511: foreach ( $tags as $v )
512: {
513: list($key,$value) = preg_split ( '/=/', $v, 2 );
514: $dkim[$key] = $value;
515: }
516:
517:
518:
519:
520: if ( ! preg_match ( '{(simple|simple-http|relaxed)(/(simple|simple-http|relaxed))?}', $dkim['c'], $matches ) )
521: return 'bad canonicalization:' . $dkim['c'] ;
522: if ( count ( $matches ) > 2 )
523: $this->body_cannon = $matches[2];
524: else
525: $this->body_cannon = $matches[1];
526: $this->header_cannon = $matches[1];
527:
528: if ( $dkim['a'] != 'rsa-sha1' && $dkim['a'] != 'rsa-sha256' )
529: return 'bad signing algorythm:' . $dkim['a'] ;
530:
531: if ( $dkim['q'] != 'dns/txt' )
532: return 'bad query method';
533:
534: if ( ! isset ( $dkim['d'] ) )
535: return 'missing signing domain';
536: $this->remote_server = $dkim['d'];
537:
538: if ( isset ( $dkim['i'] ) )
539: {
540:
541: if ( ! stristr ( $dkim['i'], $dkim['d'] ) )
542: return 'signing domain mismatch';
543:
544: if ( strstr ( $dkim [ 'i' ], '@' ) )
545: $this->remote_user = substr ( $dkim [ 'i' ], 0, strpos ( $dkim [ 'i' ], '@' ) - 1 );
546: }
547:
548: if ( ! isset ( $dkim['s'] ) )
549: return 'missing selector';
550: $this->remote_selector = $dkim['s'];
551:
552: if ( ! isset ( $dkim['h'] ) )
553: return 'missing list of signed headers';
554: $this->signed_headers = preg_split ( '/:/', $dkim['h'] );
555:
556: $sh = Array ();
557: foreach ( $this->signed_headers as $h )
558: {
559: $sh[] = strtolower ( $h );
560: if ( in_array ( strtolower ( $h ), $this->disallowed_headers ) )
561: return "$h is NOT allowed in signed header fields per RFC4871 or iSchedule";
562: }
563: foreach ( $this->required_headers as $h )
564: if ( ! in_array ( strtolower ( $h ), $sh ) )
565: return "$h is REQUIRED but missing in signed header fields per iSchedule";
566:
567: if ( ! isset ( $dkim['bh'] ) )
568: return 'missing body signature';
569:
570: if ( ! isset ( $dkim['b'] ) )
571: return 'missing signature in b field';
572:
573: if ( isset ( $dkim['l'] ) )
574: $this->signed_length = $dkim['l'];
575: $this->failed = false;
576: $this->DKSig = $dkim;
577: return true;
578: }
579:
580: 581: 582: 583:
584: function parseURI ( $uri )
585: {
586: if ( preg_match ( '/^mailto:([^@]+)@([^\s\t\n]+)/', $uri, $matches ) )
587: {
588: $this->remote_user = $matches[1];
589: $this->domain = $matches[2];
590: }
591: else
592: return false;
593: }
594:
595: 596: 597: 598:
599: function verifySignature ( )
600: {
601: global $request,$c;
602: $this->failed = true;
603: $signed = '';
604: foreach ( $this->signed_headers as $h )
605: if ( isset ( $_SERVER['HTTP_' . strtoupper ( strtr ( $h, '-', '_' ) ) ] ) )
606: $signed .= "$h: " . $_SERVER['HTTP_' . strtoupper ( strtr ( $h, '-', '_' ) ) ] . "\r\n";
607: else
608: $signed .= "$h: " . $_SERVER[ strtoupper ( strtr ( $h, '-', '_' ) ) ] . "\r\n";
609: if ( ! isset ( $_SERVER['HTTP_ORIGINATOR'] ) || stripos ( $signed, 'Originator' ) === false )
610: return "missing Originator";
611: if ( ! isset ( $_SERVER['HTTP_RECIPIENT'] ) || stripos ( $signed, 'Recipient' ) === false )
612: return "missing Recipient";
613: if ( ! isset ( $_SERVER['HTTP_ISCHEDULE_VERSION'] ) || $_SERVER['HTTP_ISCHEDULE_VERSION'] != '1' )
614: return "missing or mismatch ischedule-version header";
615: $body = $request->raw_post;
616: if ( ! isset ( $this->signed_length ) )
617: $this->signed_length = strlen ( $body );
618: else
619: $body = substr ( $body, 0, $this->signed_length );
620: if ( isset ( $this->remote_user_rule ) )
621: if ( $this->remote_user_rule != '*' && ! stristr ( $this->remote_user, $this->remote_user_rule ) )
622: return "remote user rule failure";
623: $hash_algo = preg_replace ( '/^.*(sha1|sha256).*/','$1', $this->DKSig['a'] );
624: $body_hash = base64_encode ( hash ( $hash_algo, $body , true ) );
625: if ( $this->DKSig['bh'] != $body_hash )
626: return "body hash mismatch";
627: $sig = $_SERVER['HTTP_DKIM_SIGNATURE'];
628: $sig = preg_replace ( '/ b=[^;\s\r\n\t]+/', ' b=', $sig );
629: $signed .= 'DKIM-Signature: ' . $sig;
630: $verify = openssl_verify ( $signed, base64_decode ( $this->DKSig['b'] ), $this->remote_public_key, $hash_algo );
631: if ( $verify != 1 )
632: {
633: openssl_sign ( $signed, $sigb, $this->schedule_private_key, $hash_algo );
634: $sigc = base64_encode ( $sigb );
635: $verify1 = openssl_verify ( $signed, $sigc, $this->remote_public_key, $hash_algo );
636: return "signature verification failed " . $this->remote_public_key . " \n\n". $sig . " \n" . $hash_algo . "\n". print_r ($verify,1) . " XX " . $verify1 . "\n";
637: }
638: $this->failed = false;
639: return true;
640: }
641:
642: 643: 644:
645: function validateRequest ( )
646: {
647: global $request;
648: if ( isset ( $_SERVER['HTTP_DKIM_SIGNATURE'] ) )
649: $sig = $_SERVER['HTTP_DKIM_SIGNATURE'];
650: else
651: {
652: $request->DoResponse( 403, translate('DKIM signature missing') );
653: return false;
654: }
655: if ( isset ( $_SERVER['HTTP_ORGANIZER'] ) )
656: $request->DoResponse( 403, translate('Organizer Missing') );
657:
658: dbg_error_log ('ischedule','beginning validation');
659: $err = $this->parseDKIM ( $sig );
660: if ( $err !== true || $this->failed )
661: $request->DoResponse( 412, 'DKIM signature invalid ' . "\n" . $err . "\n" );
662: if ( ! $this->getTxt () || $this->failed )
663: $request->DoResponse( 400, translate('DKIM signature validation failed(DNS ERROR)') );
664: if ( ! $this->parseTxt () || $this->failed )
665: $request->DoResponse( 400, translate('DKIM signature validation failed(KEY Parse ERROR)') );
666: if ( ! $this->validateKey () || $this->failed )
667: $request->DoResponse( 400, translate('DKIM signature validation failed(KEY Validation ERROR)') );
668: $err = $this->verifySignature ();
669: if ( $err !== true || $this->failed )
670: $request->DoResponse( 412, translate('DKIM signature validation failed(Signature verification ERROR)') . '\n' . $err );
671: dbg_error_log ('ischedule','signature ok');
672: return true;
673: }
674: }
675:
676: