aboutsummaryrefslogtreecommitdiff
path: root/openssl/trunk/doc/openssl_button.gif
blob: 3d3c90c9f849929d0b26bed710e00f3f6f4f88cc (plain) (blame)
ofshex dumpascii
0000 47 49 46 38 39 61 66 00 2f 00 d5 00 00 00 00 00 ff ff ff 99 99 99 cc cc cc 99 66 99 99 99 66 99 GIF89af./.................f...f.
0020 66 66 99 66 33 cc 99 66 cc 99 99 cc cc ff 99 99 cc cc 99 cc 66 99 99 ff cc ff 99 66 cc 66 99 cc ff.f3..f............f......f.f..
0040 99 cc cc 66 66 99 99 cc 99 cc cc 99 cc 66 99 cc cc 66 66 66 66 66 66 cc cc 99 ff cc ff ff ff cc ...ff........f...ffffff.........
0060 cc ff ff cc cc ff cc ff cc 99 ff 99 99 99 99 ff cc 66 cc ff ff 99 ff 99 ff 99 cc ff 99 ff ff 99 .................f..............
0080 ff cc 00 33 00 66 00 00 66 33 00 66 99 66 33 66 66 66 66 33 66 33 66 66 cc 99 99 33 99 00 00 33 ...3.f..f3.f.f3ffff3f3ff...3...3
00a0 66 33 33 33 33 33 99 33 33 33 00 33 33 33 00 66 33 99 99 99 33 99 33 66 99 cc 66 33 33 66 33 00 f33333.333.333.f3...3.3f..f33f3.
00c0 00 00 00 00 00 00 00 00 00 00 00 00 00 21 fe 16 47 49 46 20 53 6d 61 72 74 53 61 76 65 72 20 56 .............!..GIF.SmartSaver.V
00e0 65 72 31 2e 31 61 00 2c 00 00 00 00 66 00 2f 00 40 06 fe 40 80 70 48 2c 1a 8f c8 a4 72 c9 6c 3a er1.1a.,....f./.@..@.pH,....r.l:
0100 9f d0 a8 74 fa 2c 18 04 1c c3 0e 55 70 0c 06 1b 4a 6a 97 4a 0c 0c 06 ab 5a 70 bd 12 0a 02 41 81 ...t.,.....Up...Jj.J....Zp....A.
0120 c0 8e b7 1b 86 b7 7e 2e 18 08 88 17 01 0e 01 01 7f 42 32 0a 01 45 03 01 89 03 32 43 02 0e 13 44 ......~..........B2..E....2C...D
0140 03 0b 02 0f 0d 0b 12 0b 42 7d 29 35 5c 0c 06 17 07 68 69 03 29 63 5d 05 28 29 7e 17 05 03 31 28 ........B})5\....hi.)c].()~...1(
0160 2c 02 ae 2c 31 aa 63 2c 01 07 64 85 9f 3b 07 96 71 5f 03 0e 0a 1c 0a 7e 8b 96 cc 0a 89 0e 1a 02 ,..,1.c,..d..;..q_.....~........
0180 90 43 3a 03 95 9b 0d 18 12 dc 42 09 6f 6c 56 71 7a 6c a4 e8 03 ad af e5 17 6c e6 71 97 97 02 f3 .C:.......B.olVqzl.......l.q....
01a0 71 98 f6 f8 f4 0c 03 89 89 8d 03 0c e4 09 20 b0 60 01 bf 68 d1 02 58 5a 40 80 93 41 4b 10 0d 16 q...............`..h..XZ@..AK...
01c0 dc 34 84 90 10 42 8a 14 5d c4 08 00 a3 45 8b 1b 33 82 ec 58 11 a4 c6 91 1a 43 6e 54 e9 91 24 c9 .4...B..]....E..3..X.....CnT..$.
01e0 93 25 4f 72 ec 88 51 80 47 8f c6 6c de 24 a4 73 e7 fe cd 9e 3e 79 0a 0d 5a 68 68 d0 3e 40 7d c6 .%Or..Q.G..l.$.s....>y..Zhh.>@}.
0200 69 09 40 8d 01 53 06 6e a0 b9 20 d5 94 9a 39 58 09 20 90 53 81 1c 1c 37 72 da a8 d8 33 30 eb d7 i.@..S.n......9X...S...7r...30..
0220 3e 85 0c ac a0 21 43 c6 52 0d 0c e8 a1 f5 d3 a2 ad 0c 77 fc 16 fa b1 a7 20 4e 26 86 10 c0 a5 4a >....!C.R.........w......N&....J
0240 81 42 00 85 a7 56 0c a8 10 96 42 40 82 02 33 5e 25 18 e3 8a 82 9f 2f 07 6a 8c 79 35 e0 71 8a 19 .B...V....B@..3^%...../.j.y5.q..
0260 be c8 a0 30 d0 d9 92 12 bc 1a f8 d5 48 72 97 81 c2 82 da 38 c9 ee 04 e0 ca 06 01 9b bf 50 30 e3 ...0........Hr.....8.........P0.
0280 07 c5 0e 59 02 18 ac eb 32 40 c3 2f 0a cc 08 37 56 c8 2c 41 e8 14 af 53 d5 22 74 c2 c9 82 0b 4e ...Y....2@./...7V.,A...S."t....N
02a0 64 04 a0 9d 04 fb 14 75 08 12 c8 e9 42 a5 bc 79 27 26 2f aa 77 59 b1 64 4c 97 28 d9 c3 5f ff 7e d......u....B..y'&/.wY.dL.(.._.~
02c0 a5 7c f6 30 53 66 54 cf 14 e7 51 a3 3b 19 43 54 51 03 12 98 d4 4f 68 0d 98 93 82 09 ca 04 a0 7f .|.0SfT...Q.;.CTQ....Oh.........
02e0 04 2a e5 87 82 7b 51 58 20 52 17 da 43 94 80 33 fe 39 95 58 62 88 a1 e1 95 38 6d c8 51 47 1a 27 .*...{QX.R..C..3.9.Xb....8m.QG.'
0300 8e f3 46 1a 2b a6 c8 47 89 74 24 b0 40 02 71 c5 75 89 8c 32 d2 23 e3 02 01 dd 43 80 26 03 15 d4 ..F.+..G.t$.@.q.u..2.#....C.&...
0320 00 1d 9b 08 00 01 01 47 0a 61 85 55 60 50 20 00 02 05 88 47 c1 06 e2 25 96 22 8a 58 c5 91 95 1c .......G.a.U`P.....G...%.".X....
0340 2b 12 30 d6 1c 30 c2 f1 05 13 da 21 63 8d 12 0c c0 a5 8d 00 18 dc f3 80 92 66 10 c6 c2 6d 50 a1 +.0..0.....!c............f...mP.
0360 62 40 28 2c a8 73 05 3e 66 94 03 47 1c 0c 4c 10 57 59 f1 c4 61 46 3d 03 78 27 04 23 c7 ec f3 4f b@(,.s.>f..G..L.WY..aF=.x'.#...O
0380 33 43 04 c2 8c 25 69 3a 10 81 3e 44 28 00 18 1d 9c 08 61 99 2a 28 74 a6 42 9d a8 1c 40 58 01 01 3C...%i:..>D(.....a.*(t.B...@X..
03a0 b4 52 83 01 1c 30 c2 02 0a 35 1c a0 c0 18 96 45 90 ca 0e 06 04 70 67 61 cb 4c 36 4c 5f ae 15 c0 .R...0...5.....E.....pga.L6L_...
03c0 84 a4 8f 30 b1 5d a6 80 c9 16 58 53 9d e1 79 9b 01 2c 4c 45 01 03 63 10 23 9c 2b 67 e0 35 46 02 ...0.]....XS..y..,LE..c.#.+g.5F.
03e0 09 6c 91 40 6a 96 24 10 81 03 bf 40 17 5c 2a ff b1 f2 a3 2b 00 da 79 11 10 23 8a 76 54 2c 23 9a .l.@j.$....@.\*....+..y..#.vT,#.
0400 32 30 6e 36 91 e2 2b 44 3f 08 29 d0 80 27 7b 82 21 c0 01 b0 e2 c2 1b 1b 17 0c 80 00 19 bf 8c f6 20n6..+D?.)..'{.!...............
0420 05 01 57 30 63 aa 2a 07 98 91 46 01 56 24 c0 cc c5 15 6b e0 80 21 47 c8 10 c1 76 0b 28 74 a6 11 ..W0c.*...F.V$....k..!G...v.(t..
0440 81 7c c1 1d 12 de 3d c9 e5 1c 2a 28 26 b3 00 17 b4 a8 c0 c2 9c 95 f5 e3 1e 74 0c 64 cf 3c 02 fd .|....=...*(&............t.d.<..
0460 1c 47 03 f4 10 29 97 40 13 15 bd 40 03 0f b0 c9 26 1d 6d 46 2d 80 6c 53 4b 60 f5 d5 12 9c a7 f5 .G...).@...@....&.mF-.lSK`......
0480 d6 5c 1b 91 12 4d e9 81 dd de 7c 22 81 bd 9f 83 21 c1 54 44 d8 22 e9 c7 1f 47 fb 99 2d 76 d7 74 .\...M....|"....!.TD."...G..-v.t
04a0 d7 4d 45 81 78 e7 ad f7 de 7c f7 6d 52 4d 41 4d 78 20 21 82 0f fe a0 52 87 43 68 78 e2 3f ed 94 .ME.x....|.mRMAMx.!....R.Chx.?..
04c0 b6 e1 36 2d a5 54 e4 8b 2f 0e 78 84 88 63 1e e0 de 3d a5 ed f7 e7 a0 87 ee b7 92 1e a6 61 7a e9 ..6-.T../.x..c...=...........az.
04e0 57 5d 7c 3a 96 e2 c0 81 15 8b e4 94 c8 07 1c fe 3d e7 93 8f 8d 47 e7 2e 97 5c 04 4d 1d a4 04 4a W]|:............=....G...\.M...J
0500 d3 23 84 01 08 98 1e 15 1a 07 48 25 e2 c5 5d 11 af 7a 1d b1 bb 1c 7d 1e 31 23 bc 65 ed 66 08 d2 .#........H%..]..z....}.1#.e.f..
0520 c1 20 0a 75 16 f4 3e fe 30 f2 4f 41 74 40 93 97 d4 4d d3 66 bc 54 70 58 66 99 78 61 2d 8f b1 eb ...u..>.0.OAt@...M.f.TpXf.xa-...
0540 2d 16 d0 15 1d 67 c1 ae 47 2c 5e c2 b3 41 b1 48 b0 09 40 e0 d5 9d bc 80 0c 00 c5 68 13 92 0c 21 -....g..G,^..A.H..@........h...!
0560 22 33 88 81 0c 29 d0 45 28 88 a1 27 a7 3c 89 44 26 d2 0a a1 b0 22 81 d7 d1 8c 0d 78 88 83 03 8c "3...).E(..'.<.D&....".....x....
0580 d0 16 12 06 e0 5f 44 b0 8b 11 38 b0 32 4d 65 e2 47 99 18 5e 01 36 50 80 1d ec 20 01 1d 78 0c 2a ....._D...8.2Me.G..^.6P......x.*
05a0 a8 45 86 ce 14 e0 02 a7 40 c3 89 ce 22 0e 9e 8d 25 0d 1d 94 80 01 42 e8 80 78 29 c4 46 0a 01 40 .E......@..."...%.....B..x).F..@
05c0 20 bc 40 04 9b 04 c4 20 01 c0 4e 5e 56 36 80 08 c0 90 69 86 90 85 aa 88 81 86 68 45 2b 01 14 70 ..@.......N^V6....i.......hE+..p
05e0 45 0a fe a7 9b 63 50 c0 32 b7 19 08 05 1c fe b0 9b 63 f4 e1 18 c7 e0 8d 78 14 20 2c 22 14 e0 21 E....cP.2........c......x..,"..!
0600 fd f0 c3 3e 8a e0 16 f0 8d 0f 03 81 d2 46 91 64 23 18 c2 d4 e0 8d 53 39 40 29 48 a3 8a 61 18 60 ...>.........F.d#.....S9@)H..a.`
0620 33 97 d4 45 c1 90 41 01 32 6c 40 01 04 2b c3 ae 52 70 80 18 b0 a0 92 b2 28 59 bc 02 98 0c 7d b1 3..E..A.2l@..+..Rp......(Y....}.
0640 a6 38 09 d0 c6 90 24 b0 b3 46 62 6b 02 4f 51 8c 24 65 a1 0b 5c a5 aa 87 72 d8 87 2a 62 90 c6 14 .8....$..Fbk.OQ.$e..\...r..*b...
0660 28 00 7c 72 d2 15 30 82 a3 01 c2 c8 ca 50 89 b8 4e 09 8f 00 17 46 5d e0 02 27 ab a2 2b 2d 41 4b (.|r..0......P..N....F]..'..+-AK
0680 e0 d1 d2 13 1b a0 45 0a 48 53 80 68 41 eb 0a d2 e1 4c 0d d9 91 87 01 fc e2 00 eb 2c c0 6e ea f8 ......E.HS.hA....L.........,.n..
06a0 85 4b 1a f3 12 b3 aa 85 02 64 d4 08 2f c4 03 8b 07 b4 89 02 3e 29 8f 82 34 22 85 db bc 84 02 19 .K.......d../.......>)..4"......
06c0 e2 89 4f c1 ca 0c 56 88 85 00 36 50 2e f1 28 0c 98 17 30 83 2b 02 30 01 58 3d 93 0e 11 48 53 26 ..O...V...6P..(...0.+.0.X=...HS&
06e0 59 28 8c 03 44 51 9b 84 5b 65 bc 5a 20 ff be 42 14 c1 20 80 b8 a6 4c dd e1 89 28 e5 90 32 05 d8 Y(..DQ..[e.Z...B......L...(..2..
0700 47 01 1c 89 00 3f 90 93 0c c3 d8 69 ce 9a b5 05 52 ea 22 01 13 c0 e9 31 28 63 13 07 64 f3 08 04 G....?.....i....R."....1(c..d...
0720 e0 09 99 f8 71 c0 23 78 c7 75 57 e0 cd 00 2c 63 c7 a9 90 06 67 93 da 6a ff 8c 91 97 b2 7e 01 21 ....q.#x.uW...,c....g..j.....~.!
0740 97 39 08 33 ec 35 0d 58 c8 b4 0f 0a f8 98 3c 1c 11 87 b7 0a 20 9a 05 f1 83 3c 28 80 b4 3e 78 e2 .9.3.5.X......<..........<(..>x.
0760 65 2b 0a 22 3a 7e 48 0a 3f 00 93 14 ef 28 c0 90 7c 56 3b 3a 38 d6 67 f7 60 88 64 8d 56 10 7a 24 e+.":~H.?....(..|V;:8.g.`.d.V.z$
0780 ed 12 0f 58 9a 64 77 b7 89 22 1d 89 69 56 eb 06 d6 ae a6 24 9f 5d c1 83 79 88 05 62 15 36 86 61 ...X.dw.."..iV.....$.]..y..b.6.a
07a0 f4 09 78 e6 e8 59 ed 9a e6 33 86 b8 29 48 04 59 e0 66 d3 67 59 7a a4 0f b3 46 82 da d4 36 f5 d9 ..x..Y...3..)H.Y.f.gYz...F...6..
07c0 86 60 60 67 a4 35 9b de 10 88 c7 ce 28 57 74 d0 85 ae dd a6 4b dd 25 e4 87 3f 2f 59 8f da e2 a6 .``g.5......(Wt.....K.%..?/Y....
07e0 5d fb 5c 37 bb 5f 0b 2f 76 89 b0 5d f8 1f 94 f7 6b 64 c3 0f 7d ba 9b 5d f0 a6 4d 3e e5 3d 42 dc ].\7._./v..]....kd..}..]..M>.=B.
0800 b8 4b 9f 8f bc 77 be d5 cd af 7e 89 00 00 3b .K...w....~...;
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541
/* crypto/x509/x509_vfy.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 * 
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 * 
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 * 
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.]
 */

#include <stdio.h>
#include <time.h>
#include <errno.h>

#include "cryptlib.h"
#include <openssl/crypto.h>
#include <openssl/lhash.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>

static int null_callback(int ok,X509_STORE_CTX *e);
static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
static int check_chain_extensions(X509_STORE_CTX *ctx);
static int check_trust(X509_STORE_CTX *ctx);
static int check_revocation(X509_STORE_CTX *ctx);
static int check_cert(X509_STORE_CTX *ctx);
static int check_policy(X509_STORE_CTX *ctx);
static int internal_verify(X509_STORE_CTX *ctx);
const char *X509_version="X.509" OPENSSL_VERSION_PTEXT;


static int null_callback(int ok, X509_STORE_CTX *e)
	{
	return ok;
	}

#if 0
static int x509_subject_cmp(X509 **a, X509 **b)
	{
	return X509_subject_name_cmp(*a,*b);
	}
#endif

int X509_verify_cert(X509_STORE_CTX *ctx)
	{
	X509 *x,*xtmp,*chain_ss=NULL;
	X509_NAME *xn;
	int bad_chain = 0;
	X509_VERIFY_PARAM *param = ctx->param;
	int depth,i,ok=0;
	int num;
	int (*cb)(int xok,X509_STORE_CTX *xctx);
	STACK_OF(X509) *sktmp=NULL;
	if (ctx->cert == NULL)
		{
		X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
		return -1;
		}

	cb=ctx->verify_cb;

	/* first we make sure the chain we are going to build is
	 * present and that the first entry is in place */
	if (ctx->chain == NULL)
		{
		if (	((ctx->chain=sk_X509_new_null()) == NULL) ||
			(!sk_X509_push(ctx->chain,ctx->cert)))
			{
			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
			goto end;
			}
		CRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509);
		ctx->last_untrusted=1;
		}

	/* We use a temporary STACK so we can chop and hack at it */
	if (ctx->untrusted != NULL
	    && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
		{
		X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
		goto end;
		}

	num=sk_X509_num(ctx->chain);
	x=sk_X509_value(ctx->chain,num-1);
	depth=param->depth;


	for (;;)
		{
		/* If we have enough, we break */
		if (depth < num) break; /* FIXME: If this happens, we should take
		                         * note of it and, if appropriate, use the
		                         * X509_V_ERR_CERT_CHAIN_TOO_LONG error
		                         * code later.
		                         */

		/* If we are self signed, we break */
		xn=X509_get_issuer_name(x);
		if (ctx->check_issued(ctx, x,x)) break;

		/* If we were passed a cert chain, use it first */
		if (ctx->untrusted != NULL)
			{
			xtmp=find_issuer(ctx, sktmp,x);
			if (xtmp != NULL)
				{
				if (!sk_X509_push(ctx->chain,xtmp))
					{
					X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
					goto end;
					}
				CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
				sk_X509_delete_ptr(sktmp,xtmp);
				ctx->last_untrusted++;
				x=xtmp;
				num++;
				/* reparse the full chain for
				 * the next one */
				continue;
				}
			}
		break;
		}

	/* at this point, chain should contain a list of untrusted
	 * certificates.  We now need to add at least one trusted one,
	 * if possible, otherwise we complain. */

	/* Examine last certificate in chain and see if it
 	 * is self signed.
 	 */

	i=sk_X509_num(ctx->chain);
	x=sk_X509_value(ctx->chain,i-1);
	xn = X509_get_subject_name(x);
	if (ctx->check_issued(ctx, x, x))
		{
		/* we have a self signed certificate */
		if (sk_X509_num(ctx->chain) == 1)
			{
			/* We have a single self signed certificate: see if
			 * we can find it in the store. We must have an exact
			 * match to avoid possible impersonation.
			 */
			ok = ctx->get_issuer(&xtmp, ctx, x);
			if ((ok <= 0) || X509_cmp(x, xtmp)) 
				{
				ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
				ctx->current_cert=x;
				ctx->error_depth=i-1;
				if (ok == 1) X509_free(xtmp);
				bad_chain = 1;
				ok=cb(0,ctx);
				if (!ok) goto end;
				}
			else 
				{
				/* We have a match: replace certificate with store version
				 * so we get any trust settings.
				 */
				X509_free(x);
				x = xtmp;
				sk_X509_set(ctx->chain, i - 1, x);
				ctx->last_untrusted=0;
				}
			}
		else
			{
			/* extract and save self signed certificate for later use */
			chain_ss=sk_X509_pop(ctx->chain);
			ctx->last_untrusted--;
			num--;
			x=sk_X509_value(ctx->chain,num-1);
			}
		}

	/* We now lookup certs from the certificate store */
	for (;;)
		{
		/* If we have enough, we break */
		if (depth < num) break;

		/* If we are self signed, we break */
		xn=X509_get_issuer_name(x);
		if (ctx->check_issued(ctx,x,x)) break;

		ok = ctx->get_issuer(&xtmp, ctx, x);

		if (ok < 0) return ok;
		if (ok == 0) break;

		x = xtmp;
		if (!sk_X509_push(ctx->chain,x))
			{
			X509_free(xtmp);
			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
			return 0;
			}
		num++;
		}

	/* we now have our chain, lets check it... */
	xn=X509_get_issuer_name(x);

	/* Is last certificate looked up self signed? */
	if (!ctx->check_issued(ctx,x,x))
		{
		if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
			{
			if (ctx->last_untrusted >= num)
				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
			else
				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
			ctx->current_cert=x;
			}
		else
			{

			sk_X509_push(ctx->chain,chain_ss);
			num++;
			ctx->last_untrusted=num;
			ctx->current_cert=chain_ss;
			ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
			chain_ss=NULL;
			}

		ctx->error_depth=num-1;
		bad_chain = 1;
		ok=cb(0,ctx);
		if (!ok) goto end;
		}

	/* We have the chain complete: now we need to check its purpose */
	ok = check_chain_extensions(ctx);

	if (!ok) goto end;

	/* The chain extensions are OK: check trust */

	if (param->trust > 0) ok = check_trust(ctx);

	if (!ok) goto end;

	/* We may as well copy down any DSA parameters that are required */
	X509_get_pubkey_parameters(NULL,ctx->chain);

	/* Check revocation status: we do this after copying parameters
	 * because they may be needed for CRL signature verification.
	 */

	ok = ctx->check_revocation(ctx);
	if(!ok) goto end;

	/* At this point, we have a chain and need to verify it */
	if (ctx->verify != NULL)
		ok=ctx->verify(ctx);
	else
		ok=internal_verify(ctx);
	if(!ok) goto end;

#ifdef OPENSSL_RFC3779
	/* RFC 3779 path validation, now that CRL check has been done */
	ok = v3_asid_validate_path(ctx);
	if (!ok) goto end;
	ok = v3_addr_validate_path(ctx);
	if (!ok) goto end;
#endif

	/* If we get this far evaluate policies */
	if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
		ok = ctx->check_policy(ctx);
	if(!ok) goto end;
	if (0)
		{
end:
		X509_get_pubkey_parameters(NULL,ctx->chain);
		}
	if (sktmp != NULL) sk_X509_free(sktmp);
	if (chain_ss != NULL) X509_free(chain_ss);
	return ok;
	}


/* Given a STACK_OF(X509) find the issuer of cert (if any)
 */

static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
{
	int i;
	X509 *issuer;
	for (i = 0; i < sk_X509_num(sk); i++)
		{
		issuer = sk_X509_value(sk, i);
		if (ctx->check_issued(ctx, x, issuer))
			return issuer;
		}
	return NULL;
}

/* Given a possible certificate and issuer check them */

static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
{
	int ret;
	ret = X509_check_issued(issuer, x);
	if (ret == X509_V_OK)
		return 1;
	/* If we haven't asked for issuer errors don't set ctx */
	if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK))
		return 0;

	ctx->error = ret;
	ctx->current_cert = x;
	ctx->current_issuer = issuer;
	return ctx->verify_cb(0, ctx);
	return 0;
}

/* Alternative lookup method: look from a STACK stored in other_ctx */

static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
	*issuer = find_issuer(ctx, ctx->other_ctx, x);
	if (*issuer)
		{
		CRYPTO_add(&(*issuer)->references,1,CRYPTO_LOCK_X509);
		return 1;
		}
	else
		return 0;
}
	

/* Check a certificate chains extensions for consistency
 * with the supplied purpose
 */

static int check_chain_extensions(X509_STORE_CTX *ctx)
{
#ifdef OPENSSL_NO_CHAIN_VERIFY
	return 1;
#else
	int i, ok=0, must_be_ca;
	X509 *x;
	int (*cb)(int xok,X509_STORE_CTX *xctx);
	int proxy_path_length = 0;
	int allow_proxy_certs =
		!!(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
	cb=ctx->verify_cb;

	/* must_be_ca can have 1 of 3 values:
	   -1: we accept both CA and non-CA certificates, to allow direct
	       use of self-signed certificates (which are marked as CA).
	   0:  we only accept non-CA certificates.  This is currently not
	       used, but the possibility is present for future extensions.
	   1:  we only accept CA certificates.  This is currently used for
	       all certificates in the chain except the leaf certificate.
	*/
	must_be_ca = -1;

	/* A hack to keep people who don't want to modify their software
	   happy */
	if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
		allow_proxy_certs = 1;

	/* Check all untrusted certificates */
	for (i = 0; i < ctx->last_untrusted; i++)
		{
		int ret;
		x = sk_X509_value(ctx->chain, i);
		if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
			&& (x->ex_flags & EXFLAG_CRITICAL))
			{
			ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
			ctx->error_depth = i;
			ctx->current_cert = x;
			ok=cb(0,ctx);
			if (!ok) goto end;
			}
		if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY))
			{
			ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
			ctx->error_depth = i;
			ctx->current_cert = x;
			ok=cb(0,ctx);
			if (!ok) goto end;
			}
		ret = X509_check_ca(x);
		switch(must_be_ca)
			{
		case -1:
			if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
				&& (ret != 1) && (ret != 0))
				{
				ret = 0;
				ctx->error = X509_V_ERR_INVALID_CA;
				}
			else
				ret = 1;
			break;
		case 0:
			if (ret != 0)
				{
				ret = 0;
				ctx->error = X509_V_ERR_INVALID_NON_CA;
				}
			else
				ret = 1;
			break;
		default:
			if ((ret == 0)
				|| ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
					&& (ret != 1)))
				{
				ret = 0;
				ctx->error = X509_V_ERR_INVALID_CA;
				}
			else
				ret = 1;
			break;
			}
		if (ret == 0)
			{
			ctx->error_depth = i;
			ctx->current_cert = x;
			ok=cb(0,ctx);
			if (!ok) goto end;
			}
		if (ctx->param->purpose > 0)
			{
			ret = X509_check_purpose(x, ctx->param->purpose,
				must_be_ca > 0);
			if ((ret == 0)
				|| ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
					&& (ret != 1)))
				{
				ctx->error = X509_V_ERR_INVALID_PURPOSE;
				ctx->error_depth = i;
				ctx->current_cert = x;
				ok=cb(0,ctx);
				if (!ok) goto end;
				}
			}
		/* Check pathlen */
		if ((i > 1) && (x->ex_pathlen != -1)
			   && (i > (x->ex_pathlen + proxy_path_length + 1)))
			{
			ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
			ctx->error_depth = i;
			ctx->current_cert = x;
			ok=cb(0,ctx);
			if (!ok) goto end;
			}
		/* If this certificate is a proxy certificate, the next
		   certificate must be another proxy certificate or a EE
		   certificate.  If not, the next certificate must be a
		   CA certificate.  */
		if (x->ex_flags & EXFLAG_PROXY)
			{
			if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen)
				{
				ctx->error =
					X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
				ctx->error_depth = i;
				ctx->current_cert = x;
				ok=cb(0,ctx);
				if (!ok) goto end;
				}
			proxy_path_length++;
			must_be_ca = 0;
			}
		else
			must_be_ca = 1;
		}
	ok = 1;
 end:
	return ok;
#endif
}

static int check_trust(X509_STORE_CTX *ctx)
{
#ifdef OPENSSL_NO_CHAIN_VERIFY
	return 1;
#else
	int i, ok;
	X509 *x;
	int (*cb)(int xok,X509_STORE_CTX *xctx);
	cb=ctx->verify_cb;
/* For now just check the last certificate in the chain */
	i = sk_X509_num(ctx->chain) - 1;
	x = sk_X509_value(ctx->chain, i);
	ok = X509_check_trust(x, ctx->param->trust, 0);
	if (ok == X509_TRUST_TRUSTED)
		return 1;
	ctx->error_depth = i;
	ctx->current_cert = x;
	if (ok == X509_TRUST_REJECTED)
		ctx->error = X509_V_ERR_CERT_REJECTED;
	else
		ctx->error = X509_V_ERR_CERT_UNTRUSTED;
	ok = cb(0, ctx);
	return ok;
#endif
}

static int check_revocation(X509_STORE_CTX *ctx)
	{
	int i, last, ok;
	if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
		return 1;
	if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
		last = sk_X509_num(ctx->chain) - 1;
	else
		last = 0;
	for(i = 0; i <= last; i++)
		{
		ctx->error_depth = i;
		ok = check_cert(ctx);
		if (!ok) return ok;
		}
	return 1;
	}

static int check_cert(X509_STORE_CTX *ctx)
	{
	X509_CRL *crl = NULL;
	X509 *x;
	int ok, cnum;
	cnum = ctx->error_depth;
	x = sk_X509_value(ctx->chain, cnum);
	ctx->current_cert = x;
	/* Try to retrieve relevant CRL */
	ok = ctx->get_crl(ctx, &crl, x);
	/* If error looking up CRL, nothing we can do except
	 * notify callback
	 */
	if(!ok)
		{
		ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
		ok = ctx->verify_cb(0, ctx);
		goto err;
		}
	ctx->current_crl = crl;
	ok = ctx->check_crl(ctx, crl);
	if (!ok) goto err;
	ok = ctx->cert_crl(ctx, crl, x);
	err:
	ctx->current_crl = NULL;
	X509_CRL_free(crl);
	return ok;

	}

/* Check CRL times against values in X509_STORE_CTX */

static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
	{
	time_t *ptime;
	int i;
	ctx->current_crl = crl;
	if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
		ptime = &ctx->param->check_time;
	else
		ptime = NULL;

	i=X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime);
	if (i == 0)
		{
		ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
		if (!notify || !ctx->verify_cb(0, ctx))
			return 0;
		}

	if (i > 0)
		{
		ctx->error=X509_V_ERR_CRL_NOT_YET_VALID;
		if (!notify || !ctx->verify_cb(0, ctx))
			return 0;
		}

	if(X509_CRL_get_nextUpdate(crl))
		{
		i=X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime);

		if (i == 0)
			{
			ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
			if (!notify || !ctx->verify_cb(0, ctx))
				return 0;
			}

		if (i < 0)
			{
			ctx->error=X509_V_ERR_CRL_HAS_EXPIRED;
			if (!notify || !ctx->verify_cb(0, ctx))
				return 0;
			}
		}

	ctx->current_crl = NULL;

	return 1;
	}

/* Lookup CRLs from the supplied list. Look for matching isser name
 * and validity. If we can't find a valid CRL return the last one
 * with matching name. This gives more meaningful error codes. Otherwise
 * we'd get a CRL not found error if a CRL existed with matching name but
 * was invalid.
 */

static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl,
			X509_NAME *nm, STACK_OF(X509_CRL) *crls)
	{
	int i;
	X509_CRL *crl, *best_crl = NULL;
	for (i = 0; i < sk_X509_CRL_num(crls); i++)
		{
		crl = sk_X509_CRL_value(crls, i);
		if (X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
			continue;
		if (check_crl_time(ctx, crl, 0))
			{
			*pcrl = crl;
			CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509);
			return 1;
			}
		best_crl = crl;
		}
	if (best_crl)
		{
		*pcrl = best_crl;
		CRYPTO_add(&best_crl->references, 1, CRYPTO_LOCK_X509);
		}
		
	return 0;
	}

/* Retrieve CRL corresponding to certificate: currently just a
 * subject lookup: maybe use AKID later...
 */
static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x)
	{
	int ok;
	X509_CRL *crl = NULL;
	X509_OBJECT xobj;
	X509_NAME *nm;
	nm = X509_get_issuer_name(x);
	ok = get_crl_sk(ctx, &crl, nm, ctx->crls);
	if (ok)
		{
		*pcrl = crl;
		return 1;
		}

	ok = X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj);

	if (!ok)
		{
		/* If we got a near match from get_crl_sk use that */
		if (crl)
			{
			*pcrl = crl;
			return 1;
			}
		return 0;
		}

	*pcrl = xobj.data.crl;
	if (crl)
		X509_CRL_free(crl);
	return 1;
	}

/* Check CRL validity */
static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
	{
	X509 *issuer = NULL;
	EVP_PKEY *ikey = NULL;
	int ok = 0, chnum, cnum;
	cnum = ctx->error_depth;
	chnum = sk_X509_num(ctx->chain) - 1;
	/* Find CRL issuer: if not last certificate then issuer
	 * is next certificate in chain.
	 */
	if(cnum < chnum)
		issuer = sk_X509_value(ctx->chain, cnum + 1);
	else
		{
		issuer = sk_X509_value(ctx->chain, chnum);
		/* If not self signed, can't check signature */
		if(!ctx->check_issued(ctx, issuer, issuer))
			{
			ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER;
			ok = ctx->verify_cb(0, ctx);
			if(!ok) goto err;
			}
		}

	if(issuer)
		{
		/* Check for cRLSign bit if keyUsage present */
		if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
			!(issuer->ex_kusage & KU_CRL_SIGN))
			{
			ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN;
			ok = ctx->verify_cb(0, ctx);
			if(!ok) goto err;
			}

		/* Attempt to get issuer certificate public key */
		ikey = X509_get_pubkey(issuer);

		if(!ikey)
			{
			ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
			ok = ctx->verify_cb(0, ctx);
			if (!ok) goto err;
			}
		else
			{
			/* Verify CRL signature */
			if(X509_CRL_verify(crl, ikey) <= 0)
				{
				ctx->error=X509_V_ERR_CRL_SIGNATURE_FAILURE;
				ok = ctx->verify_cb(0, ctx);
				if (!ok) goto err;
				}
			}
		}

	ok = check_crl_time(ctx, crl, 1);
	if (!ok)
		goto err;

	ok = 1;

	err:
	EVP_PKEY_free(ikey);
	return ok;
	}

/* Check certificate against CRL */
static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
	{
	int idx, ok;
	X509_REVOKED rtmp;
	STACK_OF(X509_EXTENSION) *exts;
	X509_EXTENSION *ext;
	/* Look for serial number of certificate in CRL */
	rtmp.serialNumber = X509_get_serialNumber(x);
	/* Sort revoked into serial number order if not already sorted.
	 * Do this under a lock to avoid race condition.
 	 */
	if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked))
		{
		CRYPTO_w_lock(CRYPTO_LOCK_X509_CRL);
		sk_X509_REVOKED_sort(crl->crl->revoked);
		CRYPTO_w_unlock(CRYPTO_LOCK_X509_CRL);
		}
	idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
	/* If found assume revoked: want something cleverer than
	 * this to handle entry extensions in V2 CRLs.
	 */
	if(idx >= 0)
		{
		ctx->error = X509_V_ERR_CERT_REVOKED;
		ok = ctx->verify_cb(0, ctx);
		if (!ok) return 0;
		}

	if (ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
		return 1;

	/* See if we have any critical CRL extensions: since we
	 * currently don't handle any CRL extensions the CRL must be
	 * rejected. 
	 * This code accesses the X509_CRL structure directly: applications
	 * shouldn't do this.
	 */

	exts = crl->crl->extensions;

	for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++)
		{
		ext = sk_X509_EXTENSION_value(exts, idx);
		if (ext->critical > 0)
			{
			ctx->error =
				X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
			ok = ctx->verify_cb(0, ctx);
			if(!ok) return 0;
			break;
			}
		}
	return 1;
	}

static int check_policy(X509_STORE_CTX *ctx)
	{
	int ret;
	ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
				ctx->param->policies, ctx->param->flags);
	if (ret == 0)
		{
		X509err(X509_F_CHECK_POLICY,ERR_R_MALLOC_FAILURE);
		return 0;
		}
	/* Invalid or inconsistent extensions */
	if (ret == -1)
		{
		/* Locate certificates with bad extensions and notify
		 * callback.
		 */
		X509 *x;
		int i;
		for (i = 1; i < sk_X509_num(ctx->chain); i++)
			{
			x = sk_X509_value(ctx->chain, i);
			if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
				continue;
			ctx->current_cert = x;
			ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION;
			ret = ctx->verify_cb(0, ctx);
			}
		return 1;
		}
	if (ret == -2)
		{
		ctx->current_cert = NULL;
		ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
		return ctx->verify_cb(0, ctx);
		}

	if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY)
		{
		ctx->current_cert = NULL;
		ctx->error = X509_V_OK;
		if (!ctx->verify_cb(2, ctx))
			return 0;
		}

	return 1;
	}

static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
	{
	time_t *ptime;
	int i;

	if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
		ptime = &ctx->param->check_time;
	else
		ptime = NULL;

	i=X509_cmp_time(X509_get_notBefore(x), ptime);
	if (i == 0)
		{
		ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
		ctx->current_cert=x;
		if (!ctx->verify_cb(0, ctx))
			return 0;
		}

	if (i > 0)
		{
		ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
		ctx->current_cert=x;
		if (!ctx->verify_cb(0, ctx))
			return 0;
		}

	i=X509_cmp_time(X509_get_notAfter(x), ptime);
	if (i == 0)
		{
		ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
		ctx->current_cert=x;
		if (!ctx->verify_cb(0, ctx))
			return 0;
		}

	if (i < 0)
		{
		ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
		ctx->current_cert=x;
		if (!ctx->verify_cb(0, ctx))
			return 0;
		}

	return 1;
	}

static int internal_verify(X509_STORE_CTX *ctx)
	{
	int ok=0,n;
	X509 *xs,*xi;
	EVP_PKEY *pkey=NULL;
	int (*cb)(int xok,X509_STORE_CTX *xctx);

	cb=ctx->verify_cb;

	n=sk_X509_num(ctx->chain);
	ctx->error_depth=n-1;
	n--;
	xi=sk_X509_value(ctx->chain,n);

	if (ctx->check_issued(ctx, xi, xi))
		xs=xi;
	else
		{
		if (n <= 0)
			{
			ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
			ctx->current_cert=xi;
			ok=cb(0,ctx);
			goto end;
			}
		else
			{
			n--;
			ctx->error_depth=n;
			xs=sk_X509_value(ctx->chain,n);
			}
		}

/*	ctx->error=0;  not needed */
	while (n >= 0)
		{
		ctx->error_depth=n;
		if (!xs->valid)
			{
			if ((pkey=X509_get_pubkey(xi)) == NULL)
				{
				ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
				ctx->current_cert=xi;
				ok=(*cb)(0,ctx);
				if (!ok) goto end;
				}
			else if (X509_verify(xs,pkey) <= 0)
				/* XXX  For the final trusted self-signed cert,
				 * this is a waste of time.  That check should
				 * optional so that e.g. 'openssl x509' can be
				 * used to detect invalid self-signatures, but
				 * we don't verify again and again in SSL
				 * handshakes and the like once the cert has
				 * been declared trusted. */
				{
				ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
				ctx->current_cert=xs;
				ok=(*cb)(0,ctx);
				if (!ok)
					{
					EVP_PKEY_free(pkey);
					goto end;
					}
				}
			EVP_PKEY_free(pkey);
			pkey=NULL;
			}

		xs->valid = 1;

		ok = check_cert_time(ctx, xs);
		if (!ok)
			goto end;

		/* The last error (if any) is still in the error value */
		ctx->current_issuer=xi;
		ctx->current_cert=xs;
		ok=(*cb)(1,ctx);
		if (!ok) goto end;

		n--;
		if (n >= 0)
			{
			xi=xs;
			xs=sk_X509_value(ctx->chain,n);
			}
		}
	ok=1;
end:
	return ok;
	}

int X509_cmp_current_time(ASN1_TIME *ctm)
{
	return X509_cmp_time(ctm, NULL);
}

int X509_cmp_time(ASN1_TIME *ctm, time_t *cmp_time)
	{
	char *str;
	ASN1_TIME atm;
	long offset;
	char buff1[24],buff2[24],*p;
	int i,j;

	p=buff1;
	i=ctm->length;
	str=(char *)ctm->data;
	if (ctm->type == V_ASN1_UTCTIME)
		{
		if ((i < 11) || (i > 17)) return 0;
		memcpy(p,str,10);
		p+=10;
		str+=10;
		}
	else
		{
		if (i < 13) return 0;
		memcpy(p,str,12);
		p+=12;
		str+=12;
		}

	if ((*str == 'Z') || (*str == '-') || (*str == '+'))
		{ *(p++)='0'; *(p++)='0'; }
	else
		{ 
		*(p++)= *(str++);
		*(p++)= *(str++);
		/* Skip any fractional seconds... */
		if (*str == '.')
			{
			str++;
			while ((*str >= '0') && (*str <= '9')) str++;
			}
		
		}
	*(p++)='Z';
	*(p++)='\0';

	if (*str == 'Z')
		offset=0;
	else
		{
		if ((*str != '+') && (*str != '-'))
			return 0;
		offset=((str[1]-'0')*10+(str[2]-'0'))*60;
		offset+=(str[3]-'0')*10+(str[4]-'0');
		if (*str == '-')
			offset= -offset;
		}
	atm.type=ctm->type;
	atm.length=sizeof(buff2);
	atm.data=(unsigned char *)buff2;

	if (X509_time_adj(&atm,-offset*60, cmp_time) == NULL)
		return 0;

	if (ctm->type == V_ASN1_UTCTIME)
		{
		i=(buff1[0]-'0')*10+(buff1[1]-'0');
		if (i < 50) i+=100; /* cf. RFC 2459 */
		j=(buff2[0]-'0')*10+(buff2[1]-'0');
		if (j < 50) j+=100;

		if (i < j) return -1;
		if (i > j) return 1;
		}
	i=strcmp(buff1,buff2);
	if (i == 0) /* wait a second then return younger :-) */
		return -1;
	else
		return i;
	}

ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
{
	return X509_time_adj(s, adj, NULL);
}

ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm)
	{
	time_t t;
	int type = -1;

	if (in_tm) t = *in_tm;
	else time(&t);

	t+=adj;
	if (s) type = s->type;
	if (type == V_ASN1_UTCTIME) return ASN1_UTCTIME_set(s,t);
	if (type == V_ASN1_GENERALIZEDTIME) return ASN1_GENERALIZEDTIME_set(s, t);
	return ASN1_TIME_set(s, t);
	}

int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
	{
	EVP_PKEY *ktmp=NULL,*ktmp2;
	int i,j;

	if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) return 1;

	for (i=0; i<sk_X509_num(chain); i++)
		{
		ktmp=X509_get_pubkey(sk_X509_value(chain,i));
		if (ktmp == NULL)
			{
			X509err(X509_F_X509_GET_PUBKEY_PARAMETERS,X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
			return 0;
			}
		if (!EVP_PKEY_missing_parameters(ktmp))
			break;
		else
			{
			EVP_PKEY_free(ktmp);
			ktmp=NULL;
			}
		}
	if (ktmp == NULL)
		{
		X509err(X509_F_X509_GET_PUBKEY_PARAMETERS,X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN);
		return 0;
		}

	/* first, populate the other certs */
	for (j=i-1; j >= 0; j--)
		{
		ktmp2=X509_get_pubkey(sk_X509_value(chain,j));
		EVP_PKEY_copy_parameters(ktmp2,ktmp);
		EVP_PKEY_free(ktmp2);
		}
	
	if (pkey != NULL) EVP_PKEY_copy_parameters(pkey,ktmp);
	EVP_PKEY_free(ktmp);
	return 1;
	}

int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
	{
	/* This function is (usually) called only once, by
	 * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */
	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, argl, argp,
			new_func, dup_func, free_func);
	}

int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
	{
	return CRYPTO_set_ex_data(&ctx->ex_data,idx,data);
	}

void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
	{
	return CRYPTO_get_ex_data(&ctx->ex_data,idx);
	}

int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
	{
	return ctx->error;
	}

void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
	{
	ctx->error=err;
	}

int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
	{
	return ctx->error_depth;
	}

X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
	{
	return ctx->current_cert;
	}

STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx)
	{
	return ctx->chain;
	}

STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx)
	{
	int i;
	X509 *x;
	STACK_OF(X509) *chain;
	if (!ctx->chain || !(chain = sk_X509_dup(ctx->chain))) return NULL;
	for (i = 0; i < sk_X509_num(chain); i++)
		{
		x = sk_X509_value(chain, i);
		CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
		}
	return chain;
	}

void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
	{
	ctx->cert=x;
	}

void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
	{
	ctx->untrusted=sk;
	}

void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
	{
	ctx->crls=sk;
	}

int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
	{
	return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
	}

int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
	{
	return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
	}

/* This function is used to set the X509_STORE_CTX purpose and trust
 * values. This is intended to be used when another structure has its
 * own trust and purpose values which (if set) will be inherited by
 * the ctx. If they aren't set then we will usually have a default
 * purpose in mind which should then be used to set the trust value.
 * An example of this is SSL use: an SSL structure will have its own
 * purpose and trust settings which the application can set: if they
 * aren't set then we use the default of SSL client/server.
 */

int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
				int purpose, int trust)
{
	int idx;
	/* If purpose not set use default */
	if (!purpose) purpose = def_purpose;
	/* If we have a purpose then check it is valid */
	if (purpose)
		{
		X509_PURPOSE *ptmp;
		idx = X509_PURPOSE_get_by_id(purpose);
		if (idx == -1)
			{
			X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
						X509_R_UNKNOWN_PURPOSE_ID);
			return 0;
			}
		ptmp = X509_PURPOSE_get0(idx);
		if (ptmp->trust == X509_TRUST_DEFAULT)
			{
			idx = X509_PURPOSE_get_by_id(def_purpose);
			if (idx == -1)
				{
				X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
						X509_R_UNKNOWN_PURPOSE_ID);
				return 0;
				}
			ptmp = X509_PURPOSE_get0(idx);
			}
		/* If trust not set then get from purpose default */
		if (!trust) trust = ptmp->trust;
		}
	if (trust)
		{
		idx = X509_TRUST_get_by_id(trust);
		if (idx == -1)
			{
			X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
						X509_R_UNKNOWN_TRUST_ID);
			return 0;
			}
		}

	if (purpose && !ctx->param->purpose) ctx->param->purpose = purpose;
	if (trust && !ctx->param->trust) ctx->param->trust = trust;
	return 1;
}

X509_STORE_CTX *X509_STORE_CTX_new(void)
{
	X509_STORE_CTX *ctx;
	ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
	if (!ctx)
		{
		X509err(X509_F_X509_STORE_CTX_NEW,ERR_R_MALLOC_FAILURE);
		return NULL;
		}
	memset(ctx, 0, sizeof(X509_STORE_CTX));
	return ctx;
}

void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
{
	X509_STORE_CTX_cleanup(ctx);
	OPENSSL_free(ctx);
}

int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
	     STACK_OF(X509) *chain)
	{
	int ret = 1;
	ctx->ctx=store;
	ctx->current_method=0;
	ctx->cert=x509;
	ctx->untrusted=chain;
	ctx->crls = NULL;
	ctx->last_untrusted=0;
	ctx->other_ctx=NULL;
	ctx->valid=0;
	ctx->chain=NULL;
	ctx->error=0;
	ctx->explicit_policy=0;
	ctx->error_depth=0;
	ctx->current_cert=NULL;
	ctx->current_issuer=NULL;
	ctx->tree = NULL;

	ctx->param = X509_VERIFY_PARAM_new();

	if (!ctx->param)
		{
		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
		return 0;
		}

	/* Inherit callbacks and flags from X509_STORE if not set
	 * use defaults.
	 */


	if (store)
		ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
	else
		ctx->param->flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE;

	if (store)
		{
		ctx->verify_cb = store->verify_cb;
		ctx->cleanup = store->cleanup;
		}
	else
		ctx->cleanup = 0;

	if (ret)
		ret = X509_VERIFY_PARAM_inherit(ctx->param,
					X509_VERIFY_PARAM_lookup("default"));

	if (ret == 0)
		{
		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
		return 0;
		}

	if (store && store->check_issued)
		ctx->check_issued = store->check_issued;
	else
		ctx->check_issued = check_issued;

	if (store && store->get_issuer)
		ctx->get_issuer = store->get_issuer;
	else
		ctx->get_issuer = X509_STORE_CTX_get1_issuer;

	if (store && store->verify_cb)
		ctx->verify_cb = store->verify_cb;
	else
		ctx->verify_cb = null_callback;

	if (store && store->verify)
		ctx->verify = store->verify;
	else
		ctx->verify = internal_verify;

	if (store && store->check_revocation)
		ctx->check_revocation = store->check_revocation;
	else
		ctx->check_revocation = check_revocation;

	if (store && store->get_crl)
		ctx->get_crl = store->get_crl;
	else
		ctx->get_crl = get_crl;

	if (store && store->check_crl)
		ctx->check_crl = store->check_crl;
	else
		ctx->check_crl = check_crl;

	if (store && store->cert_crl)
		ctx->cert_crl = store->cert_crl;
	else
		ctx->cert_crl = cert_crl;

	ctx->check_policy = check_policy;


	/* This memset() can't make any sense anyway, so it's removed. As
	 * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a
	 * corresponding "new" here and remove this bogus initialisation. */
	/* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */
	if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
				&(ctx->ex_data)))
		{
		OPENSSL_free(ctx);
		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
		return 0;
		}
	return 1;
	}

/* Set alternative lookup method: just a STACK of trusted certificates.
 * This avoids X509_STORE nastiness where it isn't needed.
 */

void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
{
	ctx->other_ctx = sk;
	ctx->get_issuer = get_issuer_sk;
}

void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
	{
	if (ctx->cleanup) ctx->cleanup(ctx);
	X509_VERIFY_PARAM_free(ctx->param);
	if (ctx->tree)
		X509_policy_tree_free(ctx->tree);
	if (ctx->chain != NULL)
		{
		sk_X509_pop_free(ctx->chain,X509_free);
		ctx->chain=NULL;
		}
	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data));
	memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
	}

void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth)
	{
	X509_VERIFY_PARAM_set_depth(ctx->param, depth);
	}

void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags)
	{
	X509_VERIFY_PARAM_set_flags(ctx->param, flags);
	}

void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, time_t t)
	{
	X509_VERIFY_PARAM_set_time(ctx->param, t);
	}

void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
				  int (*verify_cb)(int, X509_STORE_CTX *))
	{
	ctx->verify_cb=verify_cb;
	}

X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx)
	{
	return ctx->tree;
	}

int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx)
	{
	return ctx->explicit_policy;
	}

int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name)
	{
	const X509_VERIFY_PARAM *param;
	param = X509_VERIFY_PARAM_lookup(name);
	if (!param)
		return 0;
	return X509_VERIFY_PARAM_inherit(ctx->param, param);
	}

X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx)
	{
	return ctx->param;
	}

void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
	{
	if (ctx->param)
		X509_VERIFY_PARAM_free(ctx->param);
	ctx->param = param;
	}

IMPLEMENT_STACK_OF(X509)
IMPLEMENT_ASN1_SET_OF(X509)

IMPLEMENT_STACK_OF(X509_NAME)

IMPLEMENT_STACK_OF(X509_ATTRIBUTE)
IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE)