/[dtapublic]/to_be_filed/nixprojs/cron/2007/05/cc_kt1_auth_php/cc_kt1_auth_php.c
ViewVC logotype

Contents of /to_be_filed/nixprojs/cron/2007/05/cc_kt1_auth_php/cc_kt1_auth_php.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 17 - (show annotations) (download)
Sat Oct 8 04:11:18 2016 UTC (7 years, 5 months ago) by dashley
File MIME type: text/plain
File size: 103562 byte(s)
Initial commit.
1 //$Header: /home/dashley/cvsrep/e3ft_gpl01/e3ft_gpl01/nixprojs/cron/2007/05/cc_kt1_auth_php/cc_kt1_auth_php.c,v 1.11 2009/11/04 16:27:11 dashley Exp $
2 //-------------------------------------------------------------------------------------------------
3 //This source code and any program in which it is compiled/used is provided under the GNU GENERAL
4 //PUBLIC LICENSE, Version 3, full license text below.
5 //-------------------------------------------------------------------------------------------------
6 // GNU GENERAL PUBLIC LICENSE
7 // Version 3, 29 June 2007
8 //
9 // Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
10 // Everyone is permitted to copy and distribute verbatim copies
11 // of this license document, but changing it is not allowed.
12 //
13 // Preamble
14 //
15 // The GNU General Public License is a free, copyleft license for
16 //software and other kinds of works.
17 //
18 // The licenses for most software and other practical works are designed
19 //to take away your freedom to share and change the works. By contrast,
20 //the GNU General Public License is intended to guarantee your freedom to
21 //share and change all versions of a program--to make sure it remains free
22 //software for all its users. We, the Free Software Foundation, use the
23 //GNU General Public License for most of our software; it applies also to
24 //any other work released this way by its authors. You can apply it to
25 //your programs, too.
26 //
27 // When we speak of free software, we are referring to freedom, not
28 //price. Our General Public Licenses are designed to make sure that you
29 //have the freedom to distribute copies of free software (and charge for
30 //them if you wish), that you receive source code or can get it if you
31 //want it, that you can change the software or use pieces of it in new
32 //free programs, and that you know you can do these things.
33 //
34 // To protect your rights, we need to prevent others from denying you
35 //these rights or asking you to surrender the rights. Therefore, you have
36 //certain responsibilities if you distribute copies of the software, or if
37 //you modify it: responsibilities to respect the freedom of others.
38 //
39 // For example, if you distribute copies of such a program, whether
40 //gratis or for a fee, you must pass on to the recipients the same
41 //freedoms that you received. You must make sure that they, too, receive
42 //or can get the source code. And you must show them these terms so they
43 //know their rights.
44 //
45 // Developers that use the GNU GPL protect your rights with two steps:
46 //(1) assert copyright on the software, and (2) offer you this License
47 //giving you legal permission to copy, distribute and/or modify it.
48 //
49 // For the developers' and authors' protection, the GPL clearly explains
50 //that there is no warranty for this free software. For both users' and
51 //authors' sake, the GPL requires that modified versions be marked as
52 //changed, so that their problems will not be attributed erroneously to
53 //authors of previous versions.
54 //
55 // Some devices are designed to deny users access to install or run
56 //modified versions of the software inside them, although the manufacturer
57 //can do so. This is fundamentally incompatible with the aim of
58 //protecting users' freedom to change the software. The systematic
59 //pattern of such abuse occurs in the area of products for individuals to
60 //use, which is precisely where it is most unacceptable. Therefore, we
61 //have designed this version of the GPL to prohibit the practice for those
62 //products. If such problems arise substantially in other domains, we
63 //stand ready to extend this provision to those domains in future versions
64 //of the GPL, as needed to protect the freedom of users.
65 //
66 // Finally, every program is threatened constantly by software patents.
67 //States should not allow patents to restrict development and use of
68 //software on general-purpose computers, but in those that do, we wish to
69 //avoid the special danger that patents applied to a free program could
70 //make it effectively proprietary. To prevent this, the GPL assures that
71 //patents cannot be used to render the program non-free.
72 //
73 // The precise terms and conditions for copying, distribution and
74 //modification follow.
75 //
76 // TERMS AND CONDITIONS
77 //
78 // 0. Definitions.
79 //
80 // "This License" refers to version 3 of the GNU General Public License.
81 //
82 // "Copyright" also means copyright-like laws that apply to other kinds of
83 //works, such as semiconductor masks.
84 //
85 // "The Program" refers to any copyrightable work licensed under this
86 //License. Each licensee is addressed as "you". "Licensees" and
87 //"recipients" may be individuals or organizations.
88 //
89 // To "modify" a work means to copy from or adapt all or part of the work
90 //in a fashion requiring copyright permission, other than the making of an
91 //exact copy. The resulting work is called a "modified version" of the
92 //earlier work or a work "based on" the earlier work.
93 //
94 // A "covered work" means either the unmodified Program or a work based
95 //on the Program.
96 //
97 // To "propagate" a work means to do anything with it that, without
98 //permission, would make you directly or secondarily liable for
99 //infringement under applicable copyright law, except executing it on a
100 //computer or modifying a private copy. Propagation includes copying,
101 //distribution (with or without modification), making available to the
102 //public, and in some countries other activities as well.
103 //
104 // To "convey" a work means any kind of propagation that enables other
105 //parties to make or receive copies. Mere interaction with a user through
106 //a computer network, with no transfer of a copy, is not conveying.
107 //
108 // An interactive user interface displays "Appropriate Legal Notices"
109 //to the extent that it includes a convenient and prominently visible
110 //feature that (1) displays an appropriate copyright notice, and (2)
111 //tells the user that there is no warranty for the work (except to the
112 //extent that warranties are provided), that licensees may convey the
113 //work under this License, and how to view a copy of this License. If
114 //the interface presents a list of user commands or options, such as a
115 //menu, a prominent item in the list meets this criterion.
116 //
117 // 1. Source Code.
118 //
119 // The "source code" for a work means the preferred form of the work
120 //for making modifications to it. "Object code" means any non-source
121 //form of a work.
122 //
123 // A "Standard Interface" means an interface that either is an official
124 //standard defined by a recognized standards body, or, in the case of
125 //interfaces specified for a particular programming language, one that
126 //is widely used among developers working in that language.
127 //
128 // The "System Libraries" of an executable work include anything, other
129 //than the work as a whole, that (a) is included in the normal form of
130 //packaging a Major Component, but which is not part of that Major
131 //Component, and (b) serves only to enable use of the work with that
132 //Major Component, or to implement a Standard Interface for which an
133 //implementation is available to the public in source code form. A
134 //"Major Component", in this context, means a major essential component
135 //(kernel, window system, and so on) of the specific operating system
136 //(if any) on which the executable work runs, or a compiler used to
137 //produce the work, or an object code interpreter used to run it.
138 //
139 // The "Corresponding Source" for a work in object code form means all
140 //the source code needed to generate, install, and (for an executable
141 //work) run the object code and to modify the work, including scripts to
142 //control those activities. However, it does not include the work's
143 //System Libraries, or general-purpose tools or generally available free
144 //programs which are used unmodified in performing those activities but
145 //which are not part of the work. For example, Corresponding Source
146 //includes interface definition files associated with source files for
147 //the work, and the source code for shared libraries and dynamically
148 //linked subprograms that the work is specifically designed to require,
149 //such as by intimate data communication or control flow between those
150 //subprograms and other parts of the work.
151 //
152 // The Corresponding Source need not include anything that users
153 //can regenerate automatically from other parts of the Corresponding
154 //Source.
155 //
156 // The Corresponding Source for a work in source code form is that
157 //same work.
158 //
159 // 2. Basic Permissions.
160 //
161 // All rights granted under this License are granted for the term of
162 //copyright on the Program, and are irrevocable provided the stated
163 //conditions are met. This License explicitly affirms your unlimited
164 //permission to run the unmodified Program. The output from running a
165 //covered work is covered by this License only if the output, given its
166 //content, constitutes a covered work. This License acknowledges your
167 //rights of fair use or other equivalent, as provided by copyright law.
168 //
169 // You may make, run and propagate covered works that you do not
170 //convey, without conditions so long as your license otherwise remains
171 //in force. You may convey covered works to others for the sole purpose
172 //of having them make modifications exclusively for you, or provide you
173 //with facilities for running those works, provided that you comply with
174 //the terms of this License in conveying all material for which you do
175 //not control copyright. Those thus making or running the covered works
176 //for you must do so exclusively on your behalf, under your direction
177 //and control, on terms that prohibit them from making any copies of
178 //your copyrighted material outside their relationship with you.
179 //
180 // Conveying under any other circumstances is permitted solely under
181 //the conditions stated below. Sublicensing is not allowed; section 10
182 //makes it unnecessary.
183 //
184 // 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
185 //
186 // No covered work shall be deemed part of an effective technological
187 //measure under any applicable law fulfilling obligations under article
188 //11 of the WIPO copyright treaty adopted on 20 December 1996, or
189 //similar laws prohibiting or restricting circumvention of such
190 //measures.
191 //
192 // When you convey a covered work, you waive any legal power to forbid
193 //circumvention of technological measures to the extent such circumvention
194 //is effected by exercising rights under this License with respect to
195 //the covered work, and you disclaim any intention to limit operation or
196 //modification of the work as a means of enforcing, against the work's
197 //users, your or third parties' legal rights to forbid circumvention of
198 //technological measures.
199 //
200 // 4. Conveying Verbatim Copies.
201 //
202 // You may convey verbatim copies of the Program's source code as you
203 //receive it, in any medium, provided that you conspicuously and
204 //appropriately publish on each copy an appropriate copyright notice;
205 //keep intact all notices stating that this License and any
206 //non-permissive terms added in accord with section 7 apply to the code;
207 //keep intact all notices of the absence of any warranty; and give all
208 //recipients a copy of this License along with the Program.
209 //
210 // You may charge any price or no price for each copy that you convey,
211 //and you may offer support or warranty protection for a fee.
212 //
213 // 5. Conveying Modified Source Versions.
214 //
215 // You may convey a work based on the Program, or the modifications to
216 //produce it from the Program, in the form of source code under the
217 //terms of section 4, provided that you also meet all of these conditions:
218 //
219 // a) The work must carry prominent notices stating that you modified
220 // it, and giving a relevant date.
221 //
222 // b) The work must carry prominent notices stating that it is
223 // released under this License and any conditions added under section
224 // 7. This requirement modifies the requirement in section 4 to
225 // "keep intact all notices".
226 //
227 // c) You must license the entire work, as a whole, under this
228 // License to anyone who comes into possession of a copy. This
229 // License will therefore apply, along with any applicable section 7
230 // additional terms, to the whole of the work, and all its parts,
231 // regardless of how they are packaged. This License gives no
232 // permission to license the work in any other way, but it does not
233 // invalidate such permission if you have separately received it.
234 //
235 // d) If the work has interactive user interfaces, each must display
236 // Appropriate Legal Notices; however, if the Program has interactive
237 // interfaces that do not display Appropriate Legal Notices, your
238 // work need not make them do so.
239 //
240 // A compilation of a covered work with other separate and independent
241 //works, which are not by their nature extensions of the covered work,
242 //and which are not combined with it such as to form a larger program,
243 //in or on a volume of a storage or distribution medium, is called an
244 //"aggregate" if the compilation and its resulting copyright are not
245 //used to limit the access or legal rights of the compilation's users
246 //beyond what the individual works permit. Inclusion of a covered work
247 //in an aggregate does not cause this License to apply to the other
248 //parts of the aggregate.
249 //
250 // 6. Conveying Non-Source Forms.
251 //
252 // You may convey a covered work in object code form under the terms
253 //of sections 4 and 5, provided that you also convey the
254 //machine-readable Corresponding Source under the terms of this License,
255 //in one of these ways:
256 //
257 // a) Convey the object code in, or embodied in, a physical product
258 // (including a physical distribution medium), accompanied by the
259 // Corresponding Source fixed on a durable physical medium
260 // customarily used for software interchange.
261 //
262 // b) Convey the object code in, or embodied in, a physical product
263 // (including a physical distribution medium), accompanied by a
264 // written offer, valid for at least three years and valid for as
265 // long as you offer spare parts or customer support for that product
266 // model, to give anyone who possesses the object code either (1) a
267 // copy of the Corresponding Source for all the software in the
268 // product that is covered by this License, on a durable physical
269 // medium customarily used for software interchange, for a price no
270 // more than your reasonable cost of physically performing this
271 // conveying of source, or (2) access to copy the
272 // Corresponding Source from a network server at no charge.
273 //
274 // c) Convey individual copies of the object code with a copy of the
275 // written offer to provide the Corresponding Source. This
276 // alternative is allowed only occasionally and noncommercially, and
277 // only if you received the object code with such an offer, in accord
278 // with subsection 6b.
279 //
280 // d) Convey the object code by offering access from a designated
281 // place (gratis or for a charge), and offer equivalent access to the
282 // Corresponding Source in the same way through the same place at no
283 // further charge. You need not require recipients to copy the
284 // Corresponding Source along with the object code. If the place to
285 // copy the object code is a network server, the Corresponding Source
286 // may be on a different server (operated by you or a third party)
287 // that supports equivalent copying facilities, provided you maintain
288 // clear directions next to the object code saying where to find the
289 // Corresponding Source. Regardless of what server hosts the
290 // Corresponding Source, you remain obligated to ensure that it is
291 // available for as long as needed to satisfy these requirements.
292 //
293 // e) Convey the object code using peer-to-peer transmission, provided
294 // you inform other peers where the object code and Corresponding
295 // Source of the work are being offered to the general public at no
296 // charge under subsection 6d.
297 //
298 // A separable portion of the object code, whose source code is excluded
299 //from the Corresponding Source as a System Library, need not be
300 //included in conveying the object code work.
301 //
302 // A "User Product" is either (1) a "consumer product", which means any
303 //tangible personal property which is normally used for personal, family,
304 //or household purposes, or (2) anything designed or sold for incorporation
305 //into a dwelling. In determining whether a product is a consumer product,
306 //doubtful cases shall be resolved in favor of coverage. For a particular
307 //product received by a particular user, "normally used" refers to a
308 //typical or common use of that class of product, regardless of the status
309 //of the particular user or of the way in which the particular user
310 //actually uses, or expects or is expected to use, the product. A product
311 //is a consumer product regardless of whether the product has substantial
312 //commercial, industrial or non-consumer uses, unless such uses represent
313 //the only significant mode of use of the product.
314 //
315 // "Installation Information" for a User Product means any methods,
316 //procedures, authorization keys, or other information required to install
317 //and execute modified versions of a covered work in that User Product from
318 //a modified version of its Corresponding Source. The information must
319 //suffice to ensure that the continued functioning of the modified object
320 //code is in no case prevented or interfered with solely because
321 //modification has been made.
322 //
323 // If you convey an object code work under this section in, or with, or
324 //specifically for use in, a User Product, and the conveying occurs as
325 //part of a transaction in which the right of possession and use of the
326 //User Product is transferred to the recipient in perpetuity or for a
327 //fixed term (regardless of how the transaction is characterized), the
328 //Corresponding Source conveyed under this section must be accompanied
329 //by the Installation Information. But this requirement does not apply
330 //if neither you nor any third party retains the ability to install
331 //modified object code on the User Product (for example, the work has
332 //been installed in ROM).
333 //
334 // The requirement to provide Installation Information does not include a
335 //requirement to continue to provide support service, warranty, or updates
336 //for a work that has been modified or installed by the recipient, or for
337 //the User Product in which it has been modified or installed. Access to a
338 //network may be denied when the modification itself materially and
339 //adversely affects the operation of the network or violates the rules and
340 //protocols for communication across the network.
341 //
342 // Corresponding Source conveyed, and Installation Information provided,
343 //in accord with this section must be in a format that is publicly
344 //documented (and with an implementation available to the public in
345 //source code form), and must require no special password or key for
346 //unpacking, reading or copying.
347 //
348 // 7. Additional Terms.
349 //
350 // "Additional permissions" are terms that supplement the terms of this
351 //License by making exceptions from one or more of its conditions.
352 //Additional permissions that are applicable to the entire Program shall
353 //be treated as though they were included in this License, to the extent
354 //that they are valid under applicable law. If additional permissions
355 //apply only to part of the Program, that part may be used separately
356 //under those permissions, but the entire Program remains governed by
357 //this License without regard to the additional permissions.
358 //
359 // When you convey a copy of a covered work, you may at your option
360 //remove any additional permissions from that copy, or from any part of
361 //it. (Additional permissions may be written to require their own
362 //removal in certain cases when you modify the work.) You may place
363 //additional permissions on material, added by you to a covered work,
364 //for which you have or can give appropriate copyright permission.
365 //
366 // Notwithstanding any other provision of this License, for material you
367 //add to a covered work, you may (if authorized by the copyright holders of
368 //that material) supplement the terms of this License with terms:
369 //
370 // a) Disclaiming warranty or limiting liability differently from the
371 // terms of sections 15 and 16 of this License; or
372 //
373 // b) Requiring preservation of specified reasonable legal notices or
374 // author attributions in that material or in the Appropriate Legal
375 // Notices displayed by works containing it; or
376 //
377 // c) Prohibiting misrepresentation of the origin of that material, or
378 // requiring that modified versions of such material be marked in
379 // reasonable ways as different from the original version; or
380 //
381 // d) Limiting the use for publicity purposes of names of licensors or
382 // authors of the material; or
383 //
384 // e) Declining to grant rights under trademark law for use of some
385 // trade names, trademarks, or service marks; or
386 //
387 // f) Requiring indemnification of licensors and authors of that
388 // material by anyone who conveys the material (or modified versions of
389 // it) with contractual assumptions of liability to the recipient, for
390 // any liability that these contractual assumptions directly impose on
391 // those licensors and authors.
392 //
393 // All other non-permissive additional terms are considered "further
394 //restrictions" within the meaning of section 10. If the Program as you
395 //received it, or any part of it, contains a notice stating that it is
396 //governed by this License along with a term that is a further
397 //restriction, you may remove that term. If a license document contains
398 //a further restriction but permits relicensing or conveying under this
399 //License, you may add to a covered work material governed by the terms
400 //of that license document, provided that the further restriction does
401 //not survive such relicensing or conveying.
402 //
403 // If you add terms to a covered work in accord with this section, you
404 //must place, in the relevant source files, a statement of the
405 //additional terms that apply to those files, or a notice indicating
406 //where to find the applicable terms.
407 //
408 // Additional terms, permissive or non-permissive, may be stated in the
409 //form of a separately written license, or stated as exceptions;
410 //the above requirements apply either way.
411 //
412 // 8. Termination.
413 //
414 // You may not propagate or modify a covered work except as expressly
415 //provided under this License. Any attempt otherwise to propagate or
416 //modify it is void, and will automatically terminate your rights under
417 //this License (including any patent licenses granted under the third
418 //paragraph of section 11).
419 //
420 // However, if you cease all violation of this License, then your
421 //license from a particular copyright holder is reinstated (a)
422 //provisionally, unless and until the copyright holder explicitly and
423 //finally terminates your license, and (b) permanently, if the copyright
424 //holder fails to notify you of the violation by some reasonable means
425 //prior to 60 days after the cessation.
426 //
427 // Moreover, your license from a particular copyright holder is
428 //reinstated permanently if the copyright holder notifies you of the
429 //violation by some reasonable means, this is the first time you have
430 //received notice of violation of this License (for any work) from that
431 //copyright holder, and you cure the violation prior to 30 days after
432 //your receipt of the notice.
433 //
434 // Termination of your rights under this section does not terminate the
435 //licenses of parties who have received copies or rights from you under
436 //this License. If your rights have been terminated and not permanently
437 //reinstated, you do not qualify to receive new licenses for the same
438 //material under section 10.
439 //
440 // 9. Acceptance Not Required for Having Copies.
441 //
442 // You are not required to accept this License in order to receive or
443 //run a copy of the Program. Ancillary propagation of a covered work
444 //occurring solely as a consequence of using peer-to-peer transmission
445 //to receive a copy likewise does not require acceptance. However,
446 //nothing other than this License grants you permission to propagate or
447 //modify any covered work. These actions infringe copyright if you do
448 //not accept this License. Therefore, by modifying or propagating a
449 //covered work, you indicate your acceptance of this License to do so.
450 //
451 // 10. Automatic Licensing of Downstream Recipients.
452 //
453 // Each time you convey a covered work, the recipient automatically
454 //receives a license from the original licensors, to run, modify and
455 //propagate that work, subject to this License. You are not responsible
456 //for enforcing compliance by third parties with this License.
457 //
458 // An "entity transaction" is a transaction transferring control of an
459 //organization, or substantially all assets of one, or subdividing an
460 //organization, or merging organizations. If propagation of a covered
461 //work results from an entity transaction, each party to that
462 //transaction who receives a copy of the work also receives whatever
463 //licenses to the work the party's predecessor in interest had or could
464 //give under the previous paragraph, plus a right to possession of the
465 //Corresponding Source of the work from the predecessor in interest, if
466 //the predecessor has it or can get it with reasonable efforts.
467 //
468 // You may not impose any further restrictions on the exercise of the
469 //rights granted or affirmed under this License. For example, you may
470 //not impose a license fee, royalty, or other charge for exercise of
471 //rights granted under this License, and you may not initiate litigation
472 //(including a cross-claim or counterclaim in a lawsuit) alleging that
473 //any patent claim is infringed by making, using, selling, offering for
474 //sale, or importing the Program or any portion of it.
475 //
476 // 11. Patents.
477 //
478 // A "contributor" is a copyright holder who authorizes use under this
479 //License of the Program or a work on which the Program is based. The
480 //work thus licensed is called the contributor's "contributor version".
481 //
482 // A contributor's "essential patent claims" are all patent claims
483 //owned or controlled by the contributor, whether already acquired or
484 //hereafter acquired, that would be infringed by some manner, permitted
485 //by this License, of making, using, or selling its contributor version,
486 //but do not include claims that would be infringed only as a
487 //consequence of further modification of the contributor version. For
488 //purposes of this definition, "control" includes the right to grant
489 //patent sublicenses in a manner consistent with the requirements of
490 //this License.
491 //
492 // Each contributor grants you a non-exclusive, worldwide, royalty-free
493 //patent license under the contributor's essential patent claims, to
494 //make, use, sell, offer for sale, import and otherwise run, modify and
495 //propagate the contents of its contributor version.
496 //
497 // In the following three paragraphs, a "patent license" is any express
498 //agreement or commitment, however denominated, not to enforce a patent
499 //(such as an express permission to practice a patent or covenant not to
500 //sue for patent infringement). To "grant" such a patent license to a
501 //party means to make such an agreement or commitment not to enforce a
502 //patent against the party.
503 //
504 // If you convey a covered work, knowingly relying on a patent license,
505 //and the Corresponding Source of the work is not available for anyone
506 //to copy, free of charge and under the terms of this License, through a
507 //publicly available network server or other readily accessible means,
508 //then you must either (1) cause the Corresponding Source to be so
509 //available, or (2) arrange to deprive yourself of the benefit of the
510 //patent license for this particular work, or (3) arrange, in a manner
511 //consistent with the requirements of this License, to extend the patent
512 //license to downstream recipients. "Knowingly relying" means you have
513 //actual knowledge that, but for the patent license, your conveying the
514 //covered work in a country, or your recipient's use of the covered work
515 //in a country, would infringe one or more identifiable patents in that
516 //country that you have reason to believe are valid.
517 //
518 // If, pursuant to or in connection with a single transaction or
519 //arrangement, you convey, or propagate by procuring conveyance of, a
520 //covered work, and grant a patent license to some of the parties
521 //receiving the covered work authorizing them to use, propagate, modify
522 //or convey a specific copy of the covered work, then the patent license
523 //you grant is automatically extended to all recipients of the covered
524 //work and works based on it.
525 //
526 // A patent license is "discriminatory" if it does not include within
527 //the scope of its coverage, prohibits the exercise of, or is
528 //conditioned on the non-exercise of one or more of the rights that are
529 //specifically granted under this License. You may not convey a covered
530 //work if you are a party to an arrangement with a third party that is
531 //in the business of distributing software, under which you make payment
532 //to the third party based on the extent of your activity of conveying
533 //the work, and under which the third party grants, to any of the
534 //parties who would receive the covered work from you, a discriminatory
535 //patent license (a) in connection with copies of the covered work
536 //conveyed by you (or copies made from those copies), or (b) primarily
537 //for and in connection with specific products or compilations that
538 //contain the covered work, unless you entered into that arrangement,
539 //or that patent license was granted, prior to 28 March 2007.
540 //
541 // Nothing in this License shall be construed as excluding or limiting
542 //any implied license or other defenses to infringement that may
543 //otherwise be available to you under applicable patent law.
544 //
545 // 12. No Surrender of Others' Freedom.
546 //
547 // If conditions are imposed on you (whether by court order, agreement or
548 //otherwise) that contradict the conditions of this License, they do not
549 //excuse you from the conditions of this License. If you cannot convey a
550 //covered work so as to satisfy simultaneously your obligations under this
551 //License and any other pertinent obligations, then as a consequence you may
552 //not convey it at all. For example, if you agree to terms that obligate you
553 //to collect a royalty for further conveying from those to whom you convey
554 //the Program, the only way you could satisfy both those terms and this
555 //License would be to refrain entirely from conveying the Program.
556 //
557 // 13. Use with the GNU Affero General Public License.
558 //
559 // Notwithstanding any other provision of this License, you have
560 //permission to link or combine any covered work with a work licensed
561 //under version 3 of the GNU Affero General Public License into a single
562 //combined work, and to convey the resulting work. The terms of this
563 //License will continue to apply to the part which is the covered work,
564 //but the special requirements of the GNU Affero General Public License,
565 //section 13, concerning interaction through a network will apply to the
566 //combination as such.
567 //
568 // 14. Revised Versions of this License.
569 //
570 // The Free Software Foundation may publish revised and/or new versions of
571 //the GNU General Public License from time to time. Such new versions will
572 //be similar in spirit to the present version, but may differ in detail to
573 //address new problems or concerns.
574 //
575 // Each version is given a distinguishing version number. If the
576 //Program specifies that a certain numbered version of the GNU General
577 //Public License "or any later version" applies to it, you have the
578 //option of following the terms and conditions either of that numbered
579 //version or of any later version published by the Free Software
580 //Foundation. If the Program does not specify a version number of the
581 //GNU General Public License, you may choose any version ever published
582 //by the Free Software Foundation.
583 //
584 // If the Program specifies that a proxy can decide which future
585 //versions of the GNU General Public License can be used, that proxy's
586 //public statement of acceptance of a version permanently authorizes you
587 //to choose that version for the Program.
588 //
589 // Later license versions may give you additional or different
590 //permissions. However, no additional obligations are imposed on any
591 //author or copyright holder as a result of your choosing to follow a
592 //later version.
593 //
594 // 15. Disclaimer of Warranty.
595 //
596 // THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
597 //APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
598 //HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
599 //OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
600 //THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
601 //PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
602 //IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
603 //ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
604 //
605 // 16. Limitation of Liability.
606 //
607 // IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
608 //WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
609 //THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
610 //GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
611 //USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
612 //DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
613 //PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
614 //EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
615 //SUCH DAMAGES.
616 //
617 // 17. Interpretation of Sections 15 and 16.
618 //
619 // If the disclaimer of warranty and limitation of liability provided
620 //above cannot be given local legal effect according to their terms,
621 //reviewing courts shall apply local law that most closely approximates
622 //an absolute waiver of all civil liability in connection with the
623 //Program, unless a warranty or assumption of liability accompanies a
624 //copy of the Program in return for a fee.
625 //
626 // END OF TERMS AND CONDITIONS
627 //
628 // How to Apply These Terms to Your New Programs
629 //
630 // If you develop a new program, and you want it to be of the greatest
631 //possible use to the public, the best way to achieve this is to make it
632 //free software which everyone can redistribute and change under these terms.
633 //
634 // To do so, attach the following notices to the program. It is safest
635 //to attach them to the start of each source file to most effectively
636 //state the exclusion of warranty; and each file should have at least
637 //the "copyright" line and a pointer to where the full notice is found.
638 //
639 // <one line to give the program's name and a brief idea of what it does.>
640 // Copyright (C) <year> <name of author>
641 //
642 // This program is free software: you can redistribute it and/or modify
643 // it under the terms of the GNU General Public License as published by
644 // the Free Software Foundation, either version 3 of the License, or
645 // (at your option) any later version.
646 //
647 // This program is distributed in the hope that it will be useful,
648 // but WITHOUT ANY WARRANTY; without even the implied warranty of
649 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
650 // GNU General Public License for more details.
651 //
652 // You should have received a copy of the GNU General Public License
653 // along with this program. If not, see <http://www.gnu.org/licenses/>.
654 //
655 //Also add information on how to contact you by electronic and paper mail.
656 //
657 // If the program does terminal interaction, make it output a short
658 //notice like this when it starts in an interactive mode:
659 //
660 // <program> Copyright (C) <year> <name of author>
661 // This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
662 // This is free software, and you are welcome to redistribute it
663 // under certain conditions; type `show c' for details.
664 //
665 //The hypothetical commands `show w' and `show c' should show the appropriate
666 //parts of the General Public License. Of course, your program's commands
667 //might be different; for a GUI interface, you would use an "about box".
668 //
669 // You should also get your employer (if you work as a programmer) or school,
670 //if any, to sign a "copyright disclaimer" for the program, if necessary.
671 //For more information on this, and how to apply and follow the GNU GPL, see
672 //<http://www.gnu.org/licenses/>.
673 //
674 // The GNU General Public License does not permit incorporating your program
675 //into proprietary programs. If your program is a subroutine library, you
676 //may consider it more useful to permit linking proprietary applications with
677 //the library. If this is what you want to do, use the GNU Lesser General
678 //Public License instead of this License. But first, please read
679 //<http://www.gnu.org/philosophy/why-not-lgpl.html>.
680 //-------------------------------------------------------------------------------------------------
681 //------------------------------------------------------------------------
682 //cc_kt1_auth_php.c : A program to authenticate the CryptoCard KT-1
683 // keychain token from the PHP scripting language.
684 //
685 //Copyright (C)2007-2009 David T. Ashley (dashley@gmail.com).
686 //
687 //This program is free software; you can redistribute it and/or modify
688 //it under the terms of the GNU General Public License as published by
689 //the Free Software Foundation; either version 2 of the License, or
690 //(at your option) any later version.
691 //
692 //This program is distributed in the hope that it will be useful,
693 //but WITHOUT ANY WARRANTY; without even the implied warranty of
694 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
695 //GNU General Public License for more details.
696 //
697 //You should have received a copy of the GNU General Public License along
698 //with this program; if not, write to the Free Software Foundation, Inc.,
699 //51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
700 //
701 //The GPL, Version 2, is included in its entirety at the end of this
702 //source file.
703 //------------------------------------------------------------------------
704 //GENERAL DESCRIPTION
705 //-------------------
706 //This program is designed to be called from a PHP script and will use
707 //the AuthEngine SDK library provided by CryptoCard to verify whether an
708 //OTP (one-time password) value supplied to the program was plausibly
709 //obtained from a CryptoCard KT-1 token using certain options. It is
710 //assumed that input to the program comes from stdin and that output
711 //should be written to stdout (both presumed to be set up as pipes by the
712 //invoking PHP script).
713 //
714 //This program is designed to operate on *nix systems only and, although
715 //it can probably be ported with no or few source code changes, due to
716 //the technical complexities, I cannot support the use of this program
717 //on other operating systems.
718 //------------------------------------------------------------------------
719 //COMPILATION AND INSTALLATION INSTRUCTIONS
720 //-----------------------------------------
721 // a)Obtain the library (libAuthentication.so) from CryptoCard and
722 // install it as recommended on your *nix system. (The recommended
723 // contact at CryptoCard is Bill LaHam.)
724 //
725 // b)Place this file (cc_kt1_auth_php.c) and the header file from
726 // CryptoCard (Authentication.h) is a working directory of your
727 // choosing.
728 //
729 // c)Compile the program using the command:
730 //
731 // gcc -L. -lAuthentication -occ_kt1_auth_php cc_kt1_auth_php.c
732 //
733 // As an alternative, for development only (not for use from a PHP
734 // script), the program can be compiled with the PG_DEBUG preprocessor
735 // option:
736 //
737 // gcc -L. -lAuthentication -occ_kt1_auth_php -DPG_DEBUG cc_kt1_auth_php.c
738 //
739 // The PG_DEBUG option causes the program to emit much intermediate
740 // information; but this is useful for development or debugging only.
741 //
742 // If there are errors from the compilation to the effect that
743 // "libcrypto.so.4" is missing, it may be necessary to install
744 // openssl-0.9.7a (typically "yum install openssl097a" on a
745 // RedHat system). Recompilation should then be attempted again to
746 // determine if the error is resolved.
747 //
748 // d)Copy the executable (cc_kt1_auth_php) to a location suitable for
749 // invocation from a PHP script and set ownership and permissions
750 // appropriately. "/usr/local/bin" is a suitable location on most
751 // systems.
752 //
753 // e)Set permissions appropriately on the executable. Because disclosure
754 // of the algorithms contained in the CryptoCard library is not a
755 // security risk (these are standard algorithms), there is no reason
756 // that the executable cannot be executable by all. The recommended
757 // ownership with be root:root with permissions r-xr-xr-x ("555").
758 //
759 //Note that this program can be easily tested by file redirection or
760 //by typing input from the console. It will treat stdin and stdout
761 //the same way whether they are pipes or files.
762 //------------------------------------------------------------------------
763 //REQUIRED CRYPTOCARD KT-1 TOKEN SETUP
764 //------------------------------------
765 //The token options used were never analyzed. The default options in
766 //the example initialization program from CryptoCard proved adequate.
767 //
768 //These options are:
769 //
770 // char options[] = {0xB0, 0x9B, 0x83, 0x28, 0x00, 0x00, 0x00, 0x00};
771 //
772 //These seemed to cause the token to operate in an intuitively obvious
773 //manner, and so no further investigation was required. CryptoCard
774 //does provide a document that describes what each bitfield means.
775 //
776 //If anyone would like to reverse-engineer these options and provide
777 //a text description that I can include in this file, please e-mail
778 //me.
779 //
780 //Also, if anyone would like to modify the program to accept token
781 //options, please e-mail me.
782 //------------------------------------------------------------------------
783 //FORMAT OF STDIN
784 //---------------
785 //For simplicity, the arguments via stdin are one per line, each prefixed
786 //with a symbolic tag and a colon. The arguments may appear in any order.
787 //Certain arguments are mandatory (such as the token key), and failing to
788 //supply these arguments will cause this program to declare an unsuccessful
789 //authentication. Other arguments are optional. This program will make
790 //sensible default assumptions about any missing arguments, and will also
791 //modify its behavior somewhat based on which arguments are supplied and
792 //which are not.
793 //
794 //This program authenticates in two fundamental modes:
795 //
796 // OTP: The key, challenge, and OTP are supplied. The key must be
797 // maintained by the PHP application (typically in a database, and
798 // typically encrypted), the challenge is state information that must
799 // be maintained by the PHP script as well, and the OTP is the value
800 // displayed on the token. This program will supply the updated
801 // challenge back to the caller.
802 //
803 // RESYNC: The key, resync string, and OTP are supplied. In this
804 // case, the program will generate the challenge per the behavior
805 // of the token, then authenticate.
806 //
807 //This program determines which mode of operation based on the input
808 //lines supplied to stding.
809 //
810 //The allowable input arguments are:
811 //
812 //TOKEN_KEY: The token key is a hexadecimal representation of the 192-bit
813 //AES-192 key believed to reside in the token. This must consist of
814 //exactly 48 hexadecimal digits. This argument is always required.
815 //
816 //OTP: The 8-character OTP purported to be supplied by the token.
817 //This argument is always required.
818 //
819 //CHALLENGE: The 128-bit incrementing state believed to reside in the
820 //token. This must consist of exactly 32 hexadecimal digits. This
821 //argument is required unless the RESYNC_STRING is supplied (in which case
822 //it is ignored).
823 //
824 //RESYNC_STRING: An 8-digit numeric value that has been supplied to the
825 //token user with instructions to resynchronize the token and to provide
826 //OTP displayed. This value is optional. If this value is
827 //supplied, the challenge output of the program (the conjectured internal
828 //state of the token if the user has followed instructions) will reflect
829 //the string. If this value is not supplied, the challenge will be
830 //incremented as the token does automatically when the front panel button
831 //is pressed to obtain a new OTP.
832 //
833 //OTP_WINDOW: The number of sequential OTPs that this program will test
834 //against the supplied OTP (if a match is found, this program will
835 //indicate where in the window the match lies). The calling PHP script
836 //may implement inner window and outer window functionality using this
837 //parameter. The value of 1 (for example) corresponds to the program
838 //accepting only the expected next value of the token. The value of
839 //2 (for example) corresponds to the program accepting either the
840 //expected next value or the value after that. This parameter is optional,
841 //and a default value of 1 will be used internally if it is not supplied.
842 //------------------------------------------------------------------------
843 //FORMAT OF STDOUT
844 //----------------
845 //For simplicity, the arguments via stdout are one per line, each prefixed
846 //with a symbolic tag and a colon. All arguments will be supplied. No
847 //guarantee is made about the order (the PHP script must parse the lines).
848 //
849 //The arguments that will be provided are described below.
850 //
851 //MAJOR_RESULT: This will be a integer string, with an optional leading
852 //"-", indicating the major result of the call. The possible values are:
853 //
854 // -3 : Internal program error (anything unexpected, particularly
855 // inability to allocate memory).
856 //
857 // -2 : The input arguments to the program were syntactically defective.
858 // No authentication attempt could be made.
859 //
860 // -1 : Authentication failed. The OTP was not within the OTP_WINDOW
861 // specified.
862 //
863 // >=0 : The OTP supplied matched at least one entry in the OTP_WINDOW.
864 // The non-negative integer returned indicates which entry.
865 // 0 corresponds to the first (normally expected) entry, 1
866 // corresponds to the second, etc. This value cannot exceed
867 // OTP_WINDOW - 1.
868 //
869 //CHALLENGE: If MAJOR_RESULT is -2 or -1, the input challenge will be
870 //supplied as output. If MAJOR_RESULT >= 0, the output will be the
871 //challenge corresponding to the matched OTP, incremented and ready
872 //for the next authentication.
873 //
874 //(Note: If a RESYNC_STRING was supplied, the rules above don't change,
875 //except that the first OTP checked against is what would be expected
876 //if the token is properly resynchronized. It is most common to use
877 //OTP_WINDOW=1 when a RESYNC_STRING is supplied, so that only the single
878 //expected OTP based on the RESYNC_STRING will be checked against.)
879 //------------------------------------------------------------------------
880 #include <stdio.h>
881 #include <stdlib.h>
882 #include <string.h>
883 #include <time.h>
884
885 #include "Authentication.h"
886
887 #define PG_BUFSIZE (50000)
888 //The buffer size used for both buffering all of stdin, and for each
889 //string. Memory is so big these days, so programming large doesn't
890 //seem to be a disadvantage.
891 //
892 //Additionally, allocated memory is not free()'d, ever. The reason for this
893 //is that when the process terminates, it all gets released, so
894 //no advantage to free()'ing.
895
896 //Define FALSE and/or TRUE if they haven't been defined somewhere already.
897 //
898 #ifndef TRUE
899 #define TRUE (1)
900 #endif
901
902 #ifndef FALSE
903 #define FALSE (0)
904 #endif
905
906
907 //*******************************************************************************
908 //*** DEBUG FORMATTING/OUTPUT FUNCTIONS *****************************************
909 //*******************************************************************************
910 //
911 //Dumps a thin line to stdout.
912 void PG_hline_thin(void)
913 {
914 printf("---------------------------------------------------------------\n");
915 }
916
917
918 //Dumps a thick line to stdout.
919 void PG_hline_thick(void)
920 {
921 printf("===============================================================\n");
922 }
923
924
925 //*******************************************************************************
926 //*** FORMATTED DATA OUTPUT FUNCTIONS *******************************************
927 //*******************************************************************************
928 //
929 //Outputs a byte array to stdout.
930 //
931 void PG_byte_array_output(unsigned char *a, int len)
932 {
933 int i;
934
935 for (i=0; i<len; i++)
936 printf("%02X", a[i]);
937 }
938
939
940 //*******************************************************************************
941 //*** CHARACTER FUNCTIONS *******************************************************
942 //*******************************************************************************
943 //
944 //Returns TRUE if the passed character is a valid decimal digit,
945 //or FALSE otherwise.
946 //
947 int PG_is_decimal_digit(unsigned char arg)
948 {
949 int rv;
950
951 switch (arg)
952 {
953 case '0':
954 case '1':
955 case '2':
956 case '3':
957 case '4':
958 case '5':
959 case '6':
960 case '7':
961 case '8':
962 case '9':
963 rv = TRUE;
964 break;
965 default:
966 rv = FALSE;
967 break;
968 }
969
970 return(rv);
971 }
972
973
974 //Returns the value of the passed character decimal digit.
975 //0 is returned in the case of not a decimal digit.
976 //
977 int PG_decimal_digit_val(unsigned char arg)
978 {
979 int rv;
980
981 switch (arg)
982 {
983 case '0':
984 rv = 0;
985 break;
986 case '1':
987 rv = 1;
988 break;
989 case '2':
990 rv = 2;
991 break;
992 case '3':
993 rv = 3;
994 break;
995 case '4':
996 rv = 4;
997 break;
998 case '5':
999 rv = 5;
1000 break;
1001 case '6':
1002 rv = 6;
1003 break;
1004 case '7':
1005 rv = 7;
1006 break;
1007 case '8':
1008 rv = 8;
1009 break;
1010 case '9':
1011 rv = 9;
1012 break;
1013 default:
1014 rv = 0;
1015 break;
1016 }
1017
1018 return(rv);
1019 }
1020 //
1021 //
1022 //Returns TRUE if the passed character is a valid hexadecimal digit,
1023 //or FALSE otherwise.
1024 int PG_is_hex_digit(unsigned char arg)
1025 {
1026 int rv;
1027
1028 switch (arg)
1029 {
1030 case '0':
1031 case '1':
1032 case '2':
1033 case '3':
1034 case '4':
1035 case '5':
1036 case '6':
1037 case '7':
1038 case '8':
1039 case '9':
1040 case 'a':
1041 case 'b':
1042 case 'c':
1043 case 'd':
1044 case 'e':
1045 case 'f':
1046 case 'A':
1047 case 'B':
1048 case 'C':
1049 case 'D':
1050 case 'E':
1051 case 'F':
1052 rv = TRUE;
1053 break;
1054 default:
1055 rv = FALSE;
1056 break;
1057 }
1058
1059 return(rv);
1060 }
1061
1062
1063 //Returns the value of the passed hexadecimal digit.
1064 //0 is returned in the case of not a hex digit.
1065 int PG_hex_digit_val(unsigned char arg)
1066 {
1067 int rv;
1068
1069 switch (arg)
1070 {
1071 case '0':
1072 rv = 0;
1073 break;
1074 case '1':
1075 rv = 1;
1076 break;
1077 case '2':
1078 rv = 2;
1079 break;
1080 case '3':
1081 rv = 3;
1082 break;
1083 case '4':
1084 rv = 4;
1085 break;
1086 case '5':
1087 rv = 5;
1088 break;
1089 case '6':
1090 rv = 6;
1091 break;
1092 case '7':
1093 rv = 7;
1094 break;
1095 case '8':
1096 rv = 8;
1097 break;
1098 case '9':
1099 rv = 9;
1100 break;
1101 case 'a':
1102 case 'A':
1103 rv = 10;
1104 break;
1105 case 'b':
1106 case 'B':
1107 rv = 11;
1108 break;
1109 case 'c':
1110 case 'C':
1111 rv = 12;
1112 break;
1113 case 'd':
1114 case 'D':
1115 rv = 13;
1116 break;
1117 case 'e':
1118 case 'E':
1119 rv = 14;
1120 break;
1121 case 'f':
1122 case 'F':
1123 rv = 15;
1124 break;
1125 default:
1126 rv = 0;
1127 break;
1128 }
1129
1130 return(rv);
1131 }
1132 //
1133 //
1134 //Converts from a lower-case letter to an upper-case letter.
1135 //Characters that are not a lower-case letter are left alone.
1136 //
1137 unsigned char PG_char_to_upper(unsigned char arg)
1138 {
1139 switch (arg)
1140 {
1141 case 'a':
1142 return('A');
1143 break;
1144 case 'b':
1145 return('B');
1146 break;
1147 case 'c':
1148 return('C');
1149 break;
1150 case 'd':
1151 return('D');
1152 break;
1153 case 'e':
1154 return('E');
1155 break;
1156 case 'f':
1157 return('F');
1158 break;
1159 case 'g':
1160 return('G');
1161 break;
1162 case 'h':
1163 return('H');
1164 break;
1165 case 'i':
1166 return('I');
1167 break;
1168 case 'j':
1169 return('J');
1170 break;
1171 case 'k':
1172 return('K');
1173 break;
1174 case 'l':
1175 return('L');
1176 break;
1177 case 'm':
1178 return('M');
1179 break;
1180 case 'n':
1181 return('N');
1182 break;
1183 case 'o':
1184 return('O');
1185 break;
1186 case 'p':
1187 return('P');
1188 break;
1189 case 'q':
1190 return('Q');
1191 break;
1192 case 'r':
1193 return('R');
1194 break;
1195 case 's':
1196 return('S');
1197 break;
1198 case 't':
1199 return('T');
1200 break;
1201 case 'u':
1202 return('U');
1203 break;
1204 case 'v':
1205 return('V');
1206 break;
1207 case 'w':
1208 return('W');
1209 break;
1210 case 'x':
1211 return('X');
1212 break;
1213 case 'y':
1214 return('Y');
1215 break;
1216 case 'z':
1217 return('Z');
1218 break;
1219 default:
1220 return(arg);
1221 break;
1222 }
1223 }
1224 //
1225 //
1226 //*******************************************************************************
1227 //*** STRING FUNCTIONS **********************************************************
1228 //*******************************************************************************
1229 //
1230 //Deletes the first character of a string. If the string is zero length,
1231 //nothing is deleted.
1232 //
1233 void PG_str_first_char_delete(unsigned char *s)
1234 {
1235 int idx = 0;
1236
1237 if (*s)
1238 {
1239 do
1240 {
1241 idx++;
1242 s[idx - 1] = s[idx];
1243 }
1244 while (s[idx]);
1245 }
1246 }
1247 //
1248 //
1249 //Deletes a number of characters from the start of a string. The string will not be taken
1250 //below zero length.
1251 //
1252 void PG_str_n_char_delete(unsigned char *s, int n)
1253 {
1254 while (n)
1255 {
1256 PG_str_first_char_delete(s);
1257 n--;
1258 }
1259 }
1260 //
1261 //
1262 //Returns TRUE if a string contains characters all consistent with hexadecimal
1263 //digits, or FALSE otherwise.
1264 //
1265 int PG_str_is_all_hex_chars(unsigned char *s)
1266 {
1267 int len, i;
1268
1269 len = strlen(s);
1270
1271 for (i=0; i<len; i++)
1272 {
1273 if (! PG_is_hex_digit(s[i]))
1274 return(FALSE);
1275 }
1276
1277 return(TRUE);
1278 }
1279 //
1280 //
1281 //Translates from a zero-terminated hexadecimal string to an array of bytes.
1282 //They are assigned from [0] and then to ascending indices. The allocated
1283 //memory must be adequate to hold the data.
1284 //
1285 void PG_str_to_uchar_array(unsigned char *s, unsigned char *a)
1286 {
1287 int len, i;
1288
1289 len = strlen(s);
1290
1291 if ((len == 0) || ((len & 1) != 0)) //Can't be zero, can't be odd.
1292 return;
1293
1294 for (i=0; i<(len/2); i++)
1295 {
1296 a[i] = 0;
1297 }
1298
1299 //printf("PT1\n");
1300
1301 for (i=0; i<len; i++)
1302 {
1303 if ((i & 1) == 0)
1304 {
1305 //MSB
1306 a[i/2] |= (PG_hex_digit_val(s[i]) << 4);
1307 }
1308 else
1309 {
1310 //MSB
1311 a[i/2] |= (PG_hex_digit_val(s[i]));
1312 }
1313 }
1314 }
1315 //
1316 //
1317 //Converts any lower-case letters in a string to upper-case.
1318 //
1319 void PG_str_to_upper(unsigned char *s)
1320 {
1321 int i, len;
1322
1323 len = strlen(s);
1324
1325 for (i=0; i<len; i++)
1326 {
1327 s[i] = PG_char_to_upper(s[i]);
1328 }
1329 }
1330 //
1331 //
1332 //Sanitizes a string (in place) to contain only characters from the
1333 //allowed set. Invalid characters are removed, and the string (processed
1334 //in-place) will be the same length or shorter.
1335 //
1336 void PG_string_sanitize(unsigned char *s, const unsigned char *allowed_set)
1337 {
1338 unsigned char *getptr, *putptr;
1339
1340 getptr = putptr = s;
1341
1342 while (*getptr)
1343 {
1344 if (strchr(allowed_set, *getptr) != NULL)
1345 {
1346 //The character was found in the allowed set. Copy it over.
1347 *putptr = *getptr;
1348 putptr++;
1349 }
1350 else
1351 {
1352 //The character wasn't found. Don't copy it.
1353 }
1354
1355 getptr++;
1356 }
1357
1358 //Terminate the potentially shortened string.
1359 *putptr = 0;
1360 }
1361 //
1362 //
1363 //*******************************************************************************
1364 //*** STDIN BUFFERING FUNCTIONS *************************************************
1365 //*******************************************************************************
1366 //
1367 //Will buffer all of stdin into a buffer, dynamically allocated, returned.
1368 //On error, NULL is returned. Any extra characters left in stdin
1369 //will be read and discarded.
1370 //
1371 //For simplicity, the string returned is zero-terminated. This means that
1372 //any 0's in the input will interfere with the interpretation of the string.
1373 //However, no catastrophic consequences, so no effort put into preventing this.
1374 //There shouldn't be any 0's in the input, anyway.
1375 //
1376 unsigned char *PG_buffer_stdin(void)
1377 {
1378 unsigned char *p;
1379 int i;
1380 int c;
1381
1382 p = malloc(PG_BUFSIZE);
1383
1384 if (!p)
1385 return(NULL);
1386
1387 i = 0;
1388
1389 do
1390 {
1391 c = fgetc(stdin);
1392 if (c == EOF)
1393 {
1394 p[i] = 0;
1395 break;
1396 }
1397 else
1398 {
1399 p[i] = c;
1400 }
1401
1402 i++;
1403 } while (i < PG_BUFSIZE);
1404
1405 p[PG_BUFSIZE - 1] = 0; //Just in case read to the end.
1406
1407 //Consume the rest of stdin.
1408 while (! feof(stdin))
1409 fgetc(stdin);
1410
1411 return(p);
1412 }
1413
1414 //
1415 //Splits the stdin string into its lines. An array of pointers
1416 //is returned, terminated by a NULL pointer. In the case of an error,
1417 //the master pointer is NULL. Empty lines are discarded. The newline
1418 //characters are discarded.
1419 //
1420 unsigned char **PG_line_split(unsigned char *str_stdin)
1421 {
1422 int n_in_array = 0;
1423 //Number of entries in array, including the terminating NULL.
1424 unsigned char **rv = NULL;
1425 //Pointer to array of pointers to be returned to caller.
1426 unsigned char *cur = NULL;
1427 //Current line buffer.
1428 int getpos = 0, putpos = 0;
1429 //Position in the from array, current line at which copying
1430 //is occurring.
1431 int eolpos = 0;
1432 //Newline, \0, or one past the end of array at which the current line ends.
1433 int da_end = FALSE;
1434 //This is true if we're done.
1435 int i;
1436 //General iteration variable.
1437
1438 //Allocate an array for the array of pointers, and put in the NULL entry.
1439 rv = malloc(sizeof(unsigned char *));
1440 if (rv == NULL) //Allocation failure.
1441 return(NULL);
1442
1443 *rv = NULL; //One pointer, which is NULL.
1444 n_in_array = 1; //One element now.
1445
1446 //printf("PT1\n");
1447
1448 do
1449 {
1450 //Allocate space for a current working line.
1451 if (cur == NULL)
1452 {
1453 cur = malloc(PG_BUFSIZE);
1454 if (cur == NULL)
1455 return(NULL); //Allocation failure.
1456 }
1457
1458 //printf("PT2\n");
1459
1460 //The position at which we put stuff into the line buffer.
1461 putpos = 0;
1462
1463 //The first character to be obtained from the input buffer is at getpos.
1464 //Walk the eolpos to one past the last character that should be part of
1465 //that line.
1466 eolpos = getpos;
1467 while (
1468 (eolpos < (PG_BUFSIZE - 1))
1469 &&
1470 (str_stdin[eolpos] != '\n')
1471 &&
1472 (str_stdin[eolpos] != '\0')
1473 )
1474 {
1475 eolpos++;
1476 }
1477
1478 if (eolpos != getpos) //If we have a line of stuff.
1479 {
1480 //Copy and terminate.
1481 memcpy(cur, str_stdin + getpos, (eolpos - getpos) * sizeof(char));
1482 cur[eolpos - getpos] = 0;
1483
1484 //Add to array.
1485 rv = realloc(rv, (n_in_array + 1) * (sizeof(unsigned char *)) );
1486 if (rv == NULL)
1487 return(NULL); //Allocation failure.
1488
1489 rv[n_in_array] = NULL;
1490 rv[n_in_array - 1] = cur;
1491
1492 cur = NULL;
1493
1494 n_in_array++;
1495 }
1496
1497 //We are at the end if either we hit the last character or the zero terminator.
1498 if (
1499 (eolpos >= (PG_BUFSIZE - 1))
1500 ||
1501 (str_stdin[eolpos] == '\0')
1502 )
1503 {
1504 da_end = TRUE;
1505 }
1506 else
1507 {
1508 getpos = eolpos + 1;
1509 }
1510 } while (! da_end);
1511
1512 return(rv);
1513 }
1514 //
1515 //
1516 //*******************************************************************************
1517 //*** INPUT FILE LINE LOCATION FUNCTIONS ****************************************
1518 //*******************************************************************************
1519 //
1520 //Locates the TOKEN_KEY parameter, if it is present in the passed list
1521 //of strings, and if valid, assigns it to both the passed string and
1522 //to the passed array of bytes.
1523 //
1524 //If the TOKEN_KEY parameter is specified more than once, only the first
1525 //parameter will be used, and there will be no error reported.
1526 //
1527 //Any errors will be signalled by the var error variable, which will be
1528 //set FALSE or TRUE (TRUE on error). Not finding the key is not an error.
1529 //Finding it ill-formatted is an error.
1530 //
1531 void PG_par_token_key_locate(unsigned char **slist,
1532 unsigned char **parval,
1533 unsigned char *key, //At least 24 elements required.
1534 int *error_encountered)
1535 {
1536 unsigned char *ref = "TOKEN_KEY:";
1537 unsigned char *source_line;
1538 unsigned char *local_line;
1539
1540 *error_encountered = FALSE;
1541
1542 //Try to allocate a buffer for internal use. It won't be released.
1543 local_line = malloc(PG_BUFSIZE);
1544 if (local_line == NULL)
1545 {
1546 *error_encountered = TRUE;
1547 return;
1548 }
1549
1550 source_line = *slist;
1551
1552 while (source_line)
1553 {
1554 strcpy(local_line, source_line);
1555
1556 if (strlen(local_line) >= strlen(ref)) //Must be long enough.
1557 {
1558 if (strncmp(local_line, ref, strlen(ref)) == 0) //First part must match TOKEN_KEY:
1559 {
1560 //If yes, trash the TOKEN_KEY: tag.
1561 PG_str_n_char_delete(local_line, strlen(ref));
1562
1563 //What remains must be exactly 48 chars.
1564 if (strlen(local_line) == 48)
1565 {
1566 if (PG_str_is_all_hex_chars(local_line))
1567 {
1568 //Success at this point should be assured. Length is right, and they
1569 //are all hex characters. No further failures possible.
1570 *parval = local_line;
1571 PG_str_to_uchar_array(local_line, key);
1572 return;
1573 }
1574 else
1575 {
1576 *error_encountered = TRUE;
1577 return;
1578 }
1579 }
1580 else
1581 {
1582 *error_encountered = TRUE;
1583 return;
1584 }
1585 }
1586 }
1587
1588 slist++;
1589 source_line = *slist;
1590 }
1591 }
1592
1593 //Locates the OTP parameter, if it is present in the passed list
1594 //of strings, and if valid, assigns it to both the passed string and
1595 //to the passed array of bytes.
1596 //
1597 //If the OTP parameter is specified more than once, only the first
1598 //parameter will be used, and there will be no error reported.
1599 //
1600 //Any errors will be signalled by the var error variable, which will be
1601 //set FALSE or TRUE (TRUE on error). Not finding the key is not an error.
1602 //Finding it ill-formatted is an error.
1603 //
1604 void PG_par_otp_locate(unsigned char **slist,
1605 unsigned char **parval,
1606 int *error_encountered)
1607 {
1608 unsigned char *ref = "OTP:";
1609 unsigned char *source_line;
1610 unsigned char *local_line;
1611
1612 *error_encountered = FALSE;
1613
1614 //Try to allocate a buffer for internal use. It won't be released.
1615 local_line = malloc(PG_BUFSIZE);
1616 if (local_line == NULL)
1617 {
1618 *error_encountered = TRUE;
1619 return;
1620 }
1621
1622 source_line = *slist;
1623
1624 while (source_line)
1625 {
1626 strcpy(local_line, source_line);
1627
1628 //printf("LINE: %s\n", local_line);
1629
1630 if (strlen(local_line) >= strlen(ref)) //Must be long enough.
1631 {
1632 if (strncmp(local_line, ref, strlen(ref)) == 0) //First part must match OTP:
1633 {
1634 //If yes, trash the OTP: tag.
1635 PG_str_n_char_delete(local_line, strlen(ref));
1636
1637 //What remains must be exactly 8 chars.
1638 if (strlen(local_line) == 8)
1639 {
1640 PG_str_to_upper(local_line); //All lower-case to upper-case.
1641 PG_string_sanitize(local_line, "0123456789ABCDEFGHJKLMNPRSTUVWXY");
1642 //A token can display letters and numbers except I, O, Q, and Z.
1643 //Remove those.
1644
1645 if (strlen(local_line) == 8)
1646 {
1647 //Clear to proceed. Looks it was a reasonable OTP.
1648 *parval = local_line;
1649 return;
1650 }
1651 else
1652 {
1653 //Had some bum characters. Can't be valid.
1654 *error_encountered = TRUE;
1655 return;
1656 }
1657 }
1658 else
1659 {
1660 *error_encountered = TRUE;
1661 return;
1662 }
1663 }
1664 }
1665
1666 slist++;
1667 source_line = *slist;
1668 }
1669 }
1670
1671
1672 //Locates the CHALLENGE parameter, if it is present in the passed list
1673 //of strings, and if valid, assigns it to both the passed string and
1674 //to the passed array of bytes.
1675 //
1676 //If the CHALLENGE parameter is specified more than once, only the first
1677 //parameter will be used, and there will be no error reported.
1678 //
1679 //Any errors will be signalled by the var error variable, which will be
1680 //set FALSE or TRUE (TRUE on error). Not finding the key is not an error.
1681 //Finding it ill-formatted is an error.
1682 //
1683 void PG_par_challenge_locate(unsigned char **slist,
1684 unsigned char **parval,
1685 unsigned char *challenge, //At least 16 elements required.
1686 int *error_encountered)
1687 {
1688 unsigned char *ref = "CHALLENGE:";
1689 unsigned char *source_line;
1690 unsigned char *local_line;
1691
1692 *error_encountered = FALSE;
1693
1694 //Try to allocate a buffer for internal use. It won't be released.
1695 local_line = malloc(PG_BUFSIZE);
1696 if (local_line == NULL)
1697 {
1698 *error_encountered = TRUE;
1699 return;
1700 }
1701
1702 source_line = *slist;
1703
1704 while (source_line)
1705 {
1706 strcpy(local_line, source_line);
1707
1708 if (strlen(local_line) >= strlen(ref)) //Must be long enough.
1709 {
1710 if (strncmp(local_line, ref, strlen(ref)) == 0) //First part must match TOKEN_KEY:
1711 {
1712 //If yes, trash the CHALLENGE: tag.
1713 PG_str_n_char_delete(local_line, strlen(ref));
1714
1715 //What remains must be exactly 32 chars.
1716 if (strlen(local_line) == 32)
1717 {
1718 if (PG_str_is_all_hex_chars(local_line))
1719 {
1720 //Success at this point should be assured. Length is right, and they
1721 //are all hex characters. No further failures possible.
1722 *parval = local_line;
1723 PG_str_to_uchar_array(local_line, challenge);
1724 return;
1725 }
1726 else
1727 {
1728 *error_encountered = TRUE;
1729 return;
1730 }
1731 }
1732 else
1733 {
1734 *error_encountered = TRUE;
1735 return;
1736 }
1737 }
1738 }
1739
1740 slist++;
1741 source_line = *slist;
1742 }
1743 }
1744
1745
1746 //Locates the RESYNC_STRING parameter, if it is present in the passed list
1747 //of strings, and if valid, assigns it to both the passed string and
1748 //to the passed array of bytes.
1749 //
1750 //If the RESYNC_STRING parameter is specified more than once, only the first
1751 //parameter will be used, and there will be no error reported.
1752 //
1753 //Any errors will be signalled by the var error variable, which will be
1754 //set FALSE or TRUE (TRUE on error). Not finding the resync string is not an error.
1755 //Finding it ill-formatted is an error.
1756 //
1757 void PG_par_resync_string_locate(unsigned char **slist,
1758 unsigned char **parval,
1759 int *error_encountered)
1760 {
1761 unsigned char *ref = "RESYNC_STRING:";
1762 unsigned char *source_line;
1763 unsigned char *local_line;
1764
1765 *error_encountered = FALSE;
1766
1767 //Try to allocate a buffer for internal use. It won't be released.
1768 local_line = malloc(PG_BUFSIZE);
1769 if (local_line == NULL)
1770 {
1771 *error_encountered = TRUE;
1772 return;
1773 }
1774
1775 source_line = *slist;
1776
1777 while (source_line)
1778 {
1779 strcpy(local_line, source_line);
1780
1781 //printf("LINE: %s\n", local_line);
1782
1783 if (strlen(local_line) >= strlen(ref)) //Must be long enough.
1784 {
1785 if (strncmp(local_line, ref, strlen(ref)) == 0) //First part must match RESYNC_STRING:
1786 {
1787 //If yes, trash the RESYNC_STRING: tag.
1788 PG_str_n_char_delete(local_line, strlen(ref));
1789
1790 //What remains must be exactly 8 chars.
1791 if (strlen(local_line) == 8)
1792 {
1793 PG_string_sanitize(local_line, "0123456789");
1794 //Resync string can be only digits.
1795
1796 if (strlen(local_line) == 8)
1797 {
1798 //Clear to proceed. Looks it was a reasonable resync string.
1799 *parval = local_line;
1800 return;
1801 }
1802 else
1803 {
1804 //Had some bum characters. Can't be valid.
1805 *error_encountered = TRUE;
1806 return;
1807 }
1808 }
1809 else
1810 {
1811 *error_encountered = TRUE;
1812 return;
1813 }
1814 }
1815 }
1816
1817 slist++;
1818 source_line = *slist;
1819 }
1820 }
1821
1822 //Locates the OTP_WINDOW parameter, if it is present in the passed list
1823 //of strings, and if valid, assigns it to both the passed string and
1824 //to the passed array of bytes.
1825 //
1826 //If the OTP_WINDOW parameter is specified more than once, only the first
1827 //parameter will be used, and there will be no error reported.
1828 //
1829 //Any errors will be signalled by the var error variable, which will be
1830 //set FALSE or TRUE (TRUE on error). Not finding the resync string is not an error.
1831 //Finding it ill-formatted is an error.
1832 //
1833 void PG_par_otp_window_locate(unsigned char **slist,
1834 unsigned char **parval,
1835 int *val,
1836 int *error_encountered)
1837 {
1838 unsigned char *ref = "OTP_WINDOW:";
1839 unsigned char *source_line;
1840 unsigned char *local_line;
1841
1842 *error_encountered = FALSE;
1843
1844 //Try to allocate a buffer for internal use. It won't be released.
1845 local_line = malloc(PG_BUFSIZE);
1846 if (local_line == NULL)
1847 {
1848 *error_encountered = TRUE;
1849 return;
1850 }
1851
1852 source_line = *slist;
1853
1854 while (source_line)
1855 {
1856 strcpy(local_line, source_line);
1857
1858 //printf("LINE: %s\n", local_line);
1859
1860 if (strlen(local_line) >= strlen(ref)) //Must be long enough.
1861 {
1862 if (strncmp(local_line, ref, strlen(ref)) == 0) //First part must match OTP_WINDOW:
1863 {
1864 //If yes, trash the OTP_WINDOW tag.
1865 PG_str_n_char_delete(local_line, strlen(ref));
1866
1867 //Digits only, please.
1868 PG_string_sanitize(local_line, "0123456789");
1869
1870 //What remains must be either "0" or else must be 4 characters or less and not begin
1871 //with a "0".
1872 if (
1873 (
1874 (strlen(local_line) == 1)
1875 &&
1876 (strcmp("0", local_line) == 0)
1877 )
1878 ||
1879 (
1880 (strlen(local_line) > 0)
1881 &&
1882 (strlen(local_line) <= 4)
1883 &&
1884 (local_line[0] != '0')
1885 )
1886 )
1887 {
1888 //Clear to proceed. Looks it was a reasonable otp string.
1889 *parval = local_line;
1890 sscanf(local_line, "%d", val);
1891 return;
1892 }
1893 else
1894 {
1895 *error_encountered = TRUE;
1896 return;
1897 }
1898 }
1899 }
1900
1901 slist++;
1902 source_line = *slist;
1903 }
1904 }
1905
1906
1907 //*******************************************************************************
1908 //*** CHALLENGE MANIPULATION ****************************************************
1909 //*******************************************************************************
1910 //
1911 //Increments a challenge, processing carries from byte to byte.
1912 //
1913 void PG_challenge_increment(unsigned char *challenge)
1914 {
1915 int i;
1916
1917 for (i = 15; i >= 0; i--)
1918 {
1919 if (challenge[i] < 255)
1920 {
1921 challenge[i] = challenge[i] + 1;
1922 break;
1923 }
1924 else
1925 {
1926 challenge[i] = 0;
1927 }
1928 }
1929 }
1930
1931
1932 //*******************************************************************************
1933 //*** MAIN FUNCTION *************************************************************
1934 //*******************************************************************************
1935 //
1936 int main ( int argc, char *argv[] )
1937 {
1938 unsigned char *stdin_buffer = NULL;
1939 //The fully consumed standard input as a string, or NULL if it couldn't
1940 //be obtained.
1941 unsigned char **stdin_split = NULL;
1942 //The stdin, split into lines. This is a pointer to an array of pointers,
1943 //each of which points to a line.
1944 unsigned char *str_token_key = NULL;
1945 //The AES-192 token key as a string of hexadecimal digits, or NULL if
1946 //the token key wasn't supplied or couldn't be parsed.
1947 unsigned char *str_otp = NULL;
1948 //The token OTP supplied, or NULL if the OTP wasn't supplied or
1949 //couldn't be parsed.
1950 unsigned char *str_challenge = NULL;
1951 //A hexadecimal representation of the challenge, or NULL if it wasn't
1952 //supplied or couldn't be parsed.
1953 unsigned char *str_resync = NULL;
1954 //The resynchronization string that was given to the user to input into
1955 //the token, or NULL if it wasn't supplied or couldn't be parsed.
1956 unsigned char *str_otp_window = NULL;
1957 //A string representation of the otp window (an integer), or NULL if it
1958 //wasn't supplied or couldn't be parsed.
1959 int otp_window = 1;
1960 //The size of the window of allowed OTPs, as an integer.
1961 int error_local_encountered;
1962 //Local error flag.
1963 char token_key[24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
1964 //The AES-192 token key. Only assigned if the string could be parsed.
1965 char challenge[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
1966 //The challenge, in binary form.
1967 char options[] = {0xB0, 0x9B, 0x83, 0x28, 0x00, 0x00, 0x00, 0x00};
1968 //Token options to be used when calling into the CryptoCard library.
1969 char response_otp[9];
1970 //What the token should display. Left at 9 so can be zero-terminated.
1971 char status[110];
1972 //This dimension came from the original CryptoCard code. Have no idea how it
1973 //was determined.
1974
1975 //Grab the standard input.
1976 //
1977 stdin_buffer = PG_buffer_stdin();
1978
1979 #ifdef PG_DEBUG
1980 printf("\n*** STDIN BEFORE FILTERING START ***\n");
1981 if (stdin_buffer == NULL)
1982 printf("stdin_buffer is NULL.\n");
1983 else
1984 printf("%s\n", stdin_buffer);
1985 printf("\n*** STDIN BEFORE FILTERING END ***\n");
1986 PG_hline_thin();
1987 #endif
1988
1989 //Trim all invalid characters from the buffered standard input. No
1990 //errors are possible. Removing all the spaces makes parsing decisions
1991 //very easy. This is the lazy-man's way to do it.
1992 //
1993 if (stdin_buffer != NULL)
1994 PG_string_sanitize(stdin_buffer, ":_\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
1995
1996 #ifdef PG_DEBUG
1997 printf("\n*** STDIN AFTER FILTERING START ***\n");
1998 if (stdin_buffer == NULL)
1999 printf("stdin_buffer is NULL.\n");
2000 else
2001 printf("%s\n", stdin_buffer);
2002 printf("\n*** STDIN AFTER FILTERING END ***\n");
2003 PG_hline_thin();
2004 #endif
2005
2006 //Split the standard input into lines. In the process, empty lines are
2007 //removed. This creates an array of pointers, each pointing to a line,
2008 //NULL terminated.
2009 //
2010 if (stdin_buffer != NULL)
2011 stdin_split = PG_line_split(stdin_buffer);
2012
2013 #ifdef PG_DEBUG
2014 {
2015 int i = 0;
2016 unsigned char *p;
2017
2018 printf("\n*** STDIN AFTER LINE SPLIT START ***\n");
2019
2020 if (stdin_split != NULL)
2021 {
2022 do
2023 {
2024 p = stdin_split[i];
2025 if (p != NULL)
2026 printf("Line %6d: %s\n", i + 1, p);
2027 else
2028 printf("Line %6d: NULL\n", i + 1);
2029 i++;
2030 }
2031 while (p != NULL);
2032 }
2033 else
2034 {
2035 printf("stdin_split is NULL.\n");
2036 }
2037
2038 printf("\n*** STDIN AFTER LINE SPLIT END ***\n");
2039 PG_hline_thin();
2040 }
2041 #endif
2042
2043 //Try to obtain/parse the token key. If there is an error
2044 //or it isn't found, the string pointer will be left NULL.
2045 //
2046 if (stdin_split != NULL)
2047 PG_par_token_key_locate( stdin_split,
2048 &str_token_key,
2049 token_key,
2050 &error_local_encountered);
2051
2052
2053 #ifdef PG_DEBUG
2054 printf("\n*** TOKEN_KEY PARSE RESULTS START ***\n");
2055
2056 if (str_token_key)
2057 printf("Token key string: %s.\n", str_token_key);
2058 else
2059 printf("Token key string is NULL.\n");
2060
2061 if (str_token_key)
2062 PG_byte_array_output(token_key, sizeof(token_key)/sizeof(token_key[0]));
2063
2064 printf("\n*** TOKEN_KEY PARSE RESULTS END ***\n");
2065 PG_hline_thin();
2066 #endif
2067
2068 //Try to obtain/parse the OTP (one-time password) parameter. If it can't
2069 //be found or can't be parsed, the string pointer is left NULL.
2070 //
2071 if (stdin_split != NULL)
2072 PG_par_otp_locate( stdin_split,
2073 &str_otp,
2074 &error_local_encountered);
2075
2076 #ifdef PG_DEBUG
2077 printf("\n*** OTP PARSE RESULTS START ***\n");
2078
2079 if (str_otp)
2080 printf("OTP string: %s.\n", str_otp);
2081 else
2082 printf("OTP string is NULL.\n");
2083
2084 printf("\n*** OTP PARSE RESULTS END ***\n");
2085 PG_hline_thin();
2086 #endif
2087
2088 //Try to parse/locate the challenge parameter. If not
2089 //found or can't be parsed, leave the string pointer NULL.
2090 //
2091 if (stdin_split != NULL)
2092 PG_par_challenge_locate( stdin_split,
2093 &str_challenge,
2094 challenge,
2095 &error_local_encountered);
2096
2097 #ifdef PG_DEBUG
2098 printf("\n*** CHALLENGE PARSE RESULTS START ***\n");
2099
2100 if (str_challenge)
2101 printf("Challenge string: %s.\n", str_challenge);
2102 else
2103 printf("Challenge string is NULL.\n");
2104
2105 if (str_challenge != NULL)
2106 PG_byte_array_output(challenge, sizeof(challenge)/sizeof(challenge[0]));
2107
2108 printf("\n*** CHALLENGE PARSE RESULTS END ***\n");
2109 PG_hline_thin();
2110 #endif
2111
2112 //Try to locate/parse the resynchronization value string. If it can't
2113 //be located or parses as an error, the string pointer will be left
2114 //NULL.
2115 //
2116 if (stdin_split != NULL)
2117 PG_par_resync_string_locate( stdin_split,
2118 &str_resync,
2119 &error_local_encountered);
2120
2121 #ifdef PG_DEBUG
2122 printf("\n*** RESYNC STRING PARSE RESULTS START ***\n");
2123
2124 if (str_resync)
2125 printf("RESYNC_STRING string: %s.\n", str_resync);
2126 else
2127 printf("RESYNC_STRING string is NULL.\n");
2128
2129 printf("\n*** RESYNC STRING PARSE RESULTS END ***\n");
2130 PG_hline_thin();
2131 #endif
2132
2133 //Try to locate/parse the OTP_WINDOW parameter. If it can't
2134 //be located or can't be parsed, the string pointer will be
2135 //left NULL.
2136 //
2137 if (stdin_split != NULL)
2138 PG_par_otp_window_locate( stdin_split,
2139 &str_otp_window,
2140 &otp_window,
2141 &error_local_encountered);
2142
2143 #ifdef PG_DEBUG
2144 printf("\n*** OTP_WINDOW PARSE RESULTS START ***\n");
2145
2146 if (str_otp_window)
2147 printf("OTP_WINDOW string: %s.\n", str_otp_window);
2148 else
2149 printf("OTP_WINDOW string is NULL.\n");
2150
2151 printf("OTP_WINDOW integer : %d.\n", otp_window);
2152
2153 printf("\n*** OTP_WINDOW PARSE RESULTS END ***\n");
2154 PG_hline_thin();
2155 #endif
2156
2157 //At this point, all of the data is in. We decide what to do based on what was supplied
2158 //and what was not.
2159 //
2160 if (str_token_key == NULL)
2161 {
2162 //We can't proceed without the token key. We can do nothing. Fail the authentication.
2163 //
2164 #ifdef PG_DEBUG
2165 PG_hline_thick();
2166 printf("*** CASE: NO KEY ***\n");
2167 PG_hline_thick();
2168 #endif
2169 //
2170 printf("MAJOR_RESULT:-2\n");
2171 }
2172 else if (str_otp == NULL)
2173 {
2174 //We can't proceed without an OTP. Even for resynchronizing, an OTP is required. Fail
2175 //the authentication.
2176 //
2177 #ifdef PG_DEBUG
2178 PG_hline_thick();
2179 printf("*** CASE: NO OTP ***\n");
2180 PG_hline_thick();
2181 #endif
2182 //
2183 printf("MAJOR_RESULT:-2\n");
2184 }
2185 else if (str_resync != NULL)
2186 {
2187 int auth_success = FALSE;
2188 int i;
2189
2190 //We have a key, we have an OTP, and we have the resynchronization string that the user
2191 //was supposed to enter into the token. This is enough to authenticate. We don't need
2192 //a challenge, because that falls out of the key and the resynchronization string.
2193 //
2194 #ifdef PG_DEBUG
2195 PG_hline_thick();
2196 printf("*** CASE: RESYNCHRONIZATION ***\n");
2197 PG_hline_thick();
2198 #endif
2199
2200 //Generate the challenge that comes about from that resynchronization
2201 //string.
2202 //
2203 Generate_Challenge(str_resync, token_key, 24, 1, challenge);
2204
2205 #ifdef PG_DEBUG
2206 printf("Challenge generated: ");
2207 PG_byte_array_output(challenge, sizeof(challenge)/sizeof(challenge[0]));
2208 printf("\n");
2209 PG_hline_thin();
2210 #endif
2211
2212 //Try to match the OTP that was supplied. This will involve looping and repeatedly
2213 //checking the value against the OTP.
2214 //
2215 for (i=0; i<otp_window; i++)
2216 {
2217 #ifdef PG_DEBUG
2218 printf("OTP check loop, iteration %d of %d.\n", i+1, otp_window);
2219 #endif
2220
2221 //Try to get the value that should be displayed on the token.
2222 Authenticate(token_key, challenge, 24, 1, options, response_otp, status);
2223 response_otp[8] = 0; //Be sure zero-terminated.
2224
2225 #ifdef PG_DEBUG
2226 printf("OTP value generated from CryptoCard library: %s\n", response_otp);
2227 #endif
2228
2229 PG_challenge_increment(challenge);
2230 //Canonically, the convention used is that the value that should be stored in the
2231 //user's database is the one that will lead to the next OTP. This is not the
2232 //only convention possible.
2233
2234 if (! strcmp(str_otp, response_otp))
2235 {
2236 auth_success = TRUE;
2237 break;
2238 }
2239 }
2240
2241 if (auth_success)
2242 {
2243 //We have a match. Output the fields to indicate this.
2244 //
2245 printf("MAJOR_RESULT:%d\n", i);
2246 printf("CHALLENGE:");
2247 PG_byte_array_output(challenge, sizeof(challenge)/sizeof(challenge[0]));
2248 printf("\n");
2249 }
2250 else
2251 {
2252 //We failed to authenticate.
2253 printf("MAJOR_RESULT:-1\n");
2254 if (str_challenge != NULL)
2255 printf("CHALLENGE:%s\n", str_challenge); //If not supplied in, don't provide out.
2256 }
2257 }
2258 else if (str_challenge != NULL)
2259 {
2260 int auth_success = FALSE;
2261 int i;
2262
2263 //We have a key, we have an OTP, we don't have a resync string, and we have a challenge.
2264 //This is an ordinary authentication request.
2265 //
2266 #ifdef PG_DEBUG
2267 PG_hline_thick();
2268 printf("*** CASE: NORMAL AUTHENTICATION ***\n");
2269 PG_hline_thick();
2270 #endif
2271
2272 //Try to match the OTP that was supplied. This will involve looping and repeatedly
2273 //checking the value against the OTP.
2274 //
2275 for (i=0; i<otp_window; i++)
2276 {
2277 #ifdef PG_DEBUG
2278 printf("OTP check loop, iteration %d of %d.\n", i+1, otp_window);
2279 #endif
2280
2281 //Try to get the value that should be displayed on the token.
2282 Authenticate(token_key, challenge, 24, 1, options, response_otp, status);
2283 response_otp[8] = 0; //Be sure zero-terminated.
2284
2285 #ifdef PG_DEBUG
2286 printf("OTP value generated from CryptoCard library: %s\n", response_otp);
2287 #endif
2288
2289 PG_challenge_increment(challenge);
2290 //Canonically, the convention used is that the value that should be stored in the
2291 //user's database is the one that will lead to the next OTP. This is not the
2292 //only convention possible.
2293
2294 if (! strcmp(str_otp, response_otp))
2295 {
2296 auth_success = TRUE;
2297 break;
2298 }
2299 }
2300
2301 if (auth_success)
2302 {
2303 //We have a match. Output the fields to indicate this.
2304 //
2305 printf("MAJOR_RESULT:%d\n", i);
2306 printf("CHALLENGE:");
2307 PG_byte_array_output(challenge, sizeof(challenge)/sizeof(challenge[0]));
2308 printf("\n");
2309 }
2310 else
2311 {
2312 //We failed to authenticate.
2313 printf("MAJOR_RESULT:-1\n");
2314 printf("CHALLENGE:%s\n", str_challenge);
2315 }
2316 }
2317 else
2318 {
2319 //This didn't fall into any of the clauses above and is very odd. This is an authentication
2320 //failure.
2321 //
2322 #ifdef PG_DEBUG
2323 PG_hline_thick();
2324 printf("*** CASE: FALLTHROUGH ERROR ***\n");
2325 PG_hline_thick();
2326 #endif
2327 //
2328 printf("MAJOR_RESULT:-2\n");
2329 }
2330
2331 return(0);
2332 }
2333 //
2334 //------------------------------------------------------------------------
2335 // GNU GENERAL PUBLIC LICENSE
2336 // Version 2, June 1991
2337 //
2338 // Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
2339 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2340 // Everyone is permitted to copy and distribute verbatim copies
2341 // of this license document, but changing it is not allowed.
2342 //
2343 // Preamble
2344 //
2345 // The licenses for most software are designed to take away your
2346 //freedom to share and change it. By contrast, the GNU General Public
2347 //License is intended to guarantee your freedom to share and change free
2348 //software--to make sure the software is free for all its users. This
2349 //General Public License applies to most of the Free Software
2350 //Foundation's software and to any other program whose authors commit to
2351 //using it. (Some other Free Software Foundation software is covered by
2352 //the GNU Lesser General Public License instead.) You can apply it to
2353 //your programs, too.
2354 //
2355 // When we speak of free software, we are referring to freedom, not
2356 //price. Our General Public Licenses are designed to make sure that you
2357 //have the freedom to distribute copies of free software (and charge for
2358 //this service if you wish), that you receive source code or can get it
2359 //if you want it, that you can change the software or use pieces of it
2360 //in new free programs; and that you know you can do these things.
2361 //
2362 // To protect your rights, we need to make restrictions that forbid
2363 //anyone to deny you these rights or to ask you to surrender the rights.
2364 //These restrictions translate to certain responsibilities for you if you
2365 //distribute copies of the software, or if you modify it.
2366 //
2367 // For example, if you distribute copies of such a program, whether
2368 //gratis or for a fee, you must give the recipients all the rights that
2369 //you have. You must make sure that they, too, receive or can get the
2370 //source code. And you must show them these terms so they know their
2371 //rights.
2372 //
2373 // We protect your rights with two steps: (1) copyright the software, and
2374 //(2) offer you this license which gives you legal permission to copy,
2375 //distribute and/or modify the software.
2376 //
2377 // Also, for each author's protection and ours, we want to make certain
2378 //that everyone understands that there is no warranty for this free
2379 //software. If the software is modified by someone else and passed on, we
2380 //want its recipients to know that what they have is not the original, so
2381 //that any problems introduced by others will not reflect on the original
2382 //authors' reputations.
2383 //
2384 // Finally, any free program is threatened constantly by software
2385 //patents. We wish to avoid the danger that redistributors of a free
2386 //program will individually obtain patent licenses, in effect making the
2387 //program proprietary. To prevent this, we have made it clear that any
2388 //patent must be licensed for everyone's free use or not licensed at all.
2389 //
2390 // The precise terms and conditions for copying, distribution and
2391 //modification follow.
2392 //
2393 // GNU GENERAL PUBLIC LICENSE
2394 // TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
2395 //
2396 // 0. This License applies to any program or other work which contains
2397 //a notice placed by the copyright holder saying it may be distributed
2398 //under the terms of this General Public License. The "Program", below,
2399 //refers to any such program or work, and a "work based on the Program"
2400 //means either the Program or any derivative work under copyright law:
2401 //that is to say, a work containing the Program or a portion of it,
2402 //either verbatim or with modifications and/or translated into another
2403 //language. (Hereinafter, translation is included without limitation in
2404 //the term "modification".) Each licensee is addressed as "you".
2405 //
2406 //Activities other than copying, distribution and modification are not
2407 //covered by this License; they are outside its scope. The act of
2408 //running the Program is not restricted, and the output from the Program
2409 //is covered only if its contents constitute a work based on the
2410 //Program (independent of having been made by running the Program).
2411 //Whether that is true depends on what the Program does.
2412 //
2413 // 1. You may copy and distribute verbatim copies of the Program's
2414 //source code as you receive it, in any medium, provided that you
2415 //conspicuously and appropriately publish on each copy an appropriate
2416 //copyright notice and disclaimer of warranty; keep intact all the
2417 //notices that refer to this License and to the absence of any warranty;
2418 //and give any other recipients of the Program a copy of this License
2419 //along with the Program.
2420 //
2421 //You may charge a fee for the physical act of transferring a copy, and
2422 //you may at your option offer warranty protection in exchange for a fee.
2423 //
2424 // 2. You may modify your copy or copies of the Program or any portion
2425 //of it, thus forming a work based on the Program, and copy and
2426 //distribute such modifications or work under the terms of Section 1
2427 //above, provided that you also meet all of these conditions:
2428 //
2429 // a) You must cause the modified files to carry prominent notices
2430 // stating that you changed the files and the date of any change.
2431 //
2432 // b) You must cause any work that you distribute or publish, that in
2433 // whole or in part contains or is derived from the Program or any
2434 // part thereof, to be licensed as a whole at no charge to all third
2435 // parties under the terms of this License.
2436 //
2437 // c) If the modified program normally reads commands interactively
2438 // when run, you must cause it, when started running for such
2439 // interactive use in the most ordinary way, to print or display an
2440 // announcement including an appropriate copyright notice and a
2441 // notice that there is no warranty (or else, saying that you provide
2442 // a warranty) and that users may redistribute the program under
2443 // these conditions, and telling the user how to view a copy of this
2444 // License. (Exception: if the Program itself is interactive but
2445 // does not normally print such an announcement, your work based on
2446 // the Program is not required to print an announcement.)
2447 //
2448 //These requirements apply to the modified work as a whole. If
2449 //identifiable sections of that work are not derived from the Program,
2450 //and can be reasonably considered independent and separate works in
2451 //themselves, then this License, and its terms, do not apply to those
2452 //sections when you distribute them as separate works. But when you
2453 //distribute the same sections as part of a whole which is a work based
2454 //on the Program, the distribution of the whole must be on the terms of
2455 //this License, whose permissions for other licensees extend to the
2456 //entire whole, and thus to each and every part regardless of who wrote it.
2457 //
2458 //Thus, it is not the intent of this section to claim rights or contest
2459 //your rights to work written entirely by you; rather, the intent is to
2460 //exercise the right to control the distribution of derivative or
2461 //collective works based on the Program.
2462 //
2463 //In addition, mere aggregation of another work not based on the Program
2464 //with the Program (or with a work based on the Program) on a volume of
2465 //a storage or distribution medium does not bring the other work under
2466 //the scope of this License.
2467 //
2468 // 3. You may copy and distribute the Program (or a work based on it,
2469 //under Section 2) in object code or executable form under the terms of
2470 //Sections 1 and 2 above provided that you also do one of the following:
2471 //
2472 // a) Accompany it with the complete corresponding machine-readable
2473 // source code, which must be distributed under the terms of Sections
2474 // 1 and 2 above on a medium customarily used for software interchange; or,
2475 //
2476 // b) Accompany it with a written offer, valid for at least three
2477 // years, to give any third party, for a charge no more than your
2478 // cost of physically performing source distribution, a complete
2479 // machine-readable copy of the corresponding source code, to be
2480 // distributed under the terms of Sections 1 and 2 above on a medium
2481 // customarily used for software interchange; or,
2482 //
2483 // c) Accompany it with the information you received as to the offer
2484 // to distribute corresponding source code. (This alternative is
2485 // allowed only for noncommercial distribution and only if you
2486 // received the program in object code or executable form with such
2487 // an offer, in accord with Subsection b above.)
2488 //
2489 //The source code for a work means the preferred form of the work for
2490 //making modifications to it. For an executable work, complete source
2491 //code means all the source code for all modules it contains, plus any
2492 //associated interface definition files, plus the scripts used to
2493 //control compilation and installation of the executable. However, as a
2494 //special exception, the source code distributed need not include
2495 //anything that is normally distributed (in either source or binary
2496 //form) with the major components (compiler, kernel, and so on) of the
2497 //operating system on which the executable runs, unless that component
2498 //itself accompanies the executable.
2499 //
2500 //If distribution of executable or object code is made by offering
2501 //access to copy from a designated place, then offering equivalent
2502 //access to copy the source code from the same place counts as
2503 //distribution of the source code, even though third parties are not
2504 //compelled to copy the source along with the object code.
2505 //
2506 // 4. You may not copy, modify, sublicense, or distribute the Program
2507 //except as expressly provided under this License. Any attempt
2508 //otherwise to copy, modify, sublicense or distribute the Program is
2509 //void, and will automatically terminate your rights under this License.
2510 //However, parties who have received copies, or rights, from you under
2511 //this License will not have their licenses terminated so long as such
2512 //parties remain in full compliance.
2513 //
2514 // 5. You are not required to accept this License, since you have not
2515 //signed it. However, nothing else grants you permission to modify or
2516 //distribute the Program or its derivative works. These actions are
2517 //prohibited by law if you do not accept this License. Therefore, by
2518 //modifying or distributing the Program (or any work based on the
2519 //Program), you indicate your acceptance of this License to do so, and
2520 //all its terms and conditions for copying, distributing or modifying
2521 //the Program or works based on it.
2522 //
2523 // 6. Each time you redistribute the Program (or any work based on the
2524 //Program), the recipient automatically receives a license from the
2525 //original licensor to copy, distribute or modify the Program subject to
2526 //these terms and conditions. You may not impose any further
2527 //restrictions on the recipients' exercise of the rights granted herein.
2528 //You are not responsible for enforcing compliance by third parties to
2529 //this License.
2530 //
2531 // 7. If, as a consequence of a court judgment or allegation of patent
2532 //infringement or for any other reason (not limited to patent issues),
2533 //conditions are imposed on you (whether by court order, agreement or
2534 //otherwise) that contradict the conditions of this License, they do not
2535 //excuse you from the conditions of this License. If you cannot
2536 //distribute so as to satisfy simultaneously your obligations under this
2537 //License and any other pertinent obligations, then as a consequence you
2538 //may not distribute the Program at all. For example, if a patent
2539 //license would not permit royalty-free redistribution of the Program by
2540 //all those who receive copies directly or indirectly through you, then
2541 //the only way you could satisfy both it and this License would be to
2542 //refrain entirely from distribution of the Program.
2543 //
2544 //If any portion of this section is held invalid or unenforceable under
2545 //any particular circumstance, the balance of the section is intended to
2546 //apply and the section as a whole is intended to apply in other
2547 //circumstances.
2548 //
2549 //It is not the purpose of this section to induce you to infringe any
2550 //patents or other property right claims or to contest validity of any
2551 //such claims; this section has the sole purpose of protecting the
2552 //integrity of the free software distribution system, which is
2553 //implemented by public license practices. Many people have made
2554 //generous contributions to the wide range of software distributed
2555 //through that system in reliance on consistent application of that
2556 //system; it is up to the author/donor to decide if he or she is willing
2557 //to distribute software through any other system and a licensee cannot
2558 //impose that choice.
2559 //
2560 //This section is intended to make thoroughly clear what is believed to
2561 //be a consequence of the rest of this License.
2562 //
2563 // 8. If the distribution and/or use of the Program is restricted in
2564 //certain countries either by patents or by copyrighted interfaces, the
2565 //original copyright holder who places the Program under this License
2566 //may add an explicit geographical distribution limitation excluding
2567 //those countries, so that distribution is permitted only in or among
2568 //countries not thus excluded. In such case, this License incorporates
2569 //the limitation as if written in the body of this License.
2570 //
2571 // 9. The Free Software Foundation may publish revised and/or new versions
2572 //of the General Public License from time to time. Such new versions will
2573 //be similar in spirit to the present version, but may differ in detail to
2574 //address new problems or concerns.
2575 //
2576 //Each version is given a distinguishing version number. If the Program
2577 //specifies a version number of this License which applies to it and "any
2578 //later version", you have the option of following the terms and conditions
2579 //either of that version or of any later version published by the Free
2580 //Software Foundation. If the Program does not specify a version number of
2581 //this License, you may choose any version ever published by the Free Software
2582 //Foundation.
2583 //
2584 // 10. If you wish to incorporate parts of the Program into other free
2585 //programs whose distribution conditions are different, write to the author
2586 //to ask for permission. For software which is copyrighted by the Free
2587 //Software Foundation, write to the Free Software Foundation; we sometimes
2588 //make exceptions for this. Our decision will be guided by the two goals
2589 //of preserving the free status of all derivatives of our free software and
2590 //of promoting the sharing and reuse of software generally.
2591 //
2592 // NO WARRANTY
2593 //
2594 // 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
2595 //FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
2596 //OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
2597 //PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
2598 //OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2599 //MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
2600 //TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
2601 //PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
2602 //REPAIR OR CORRECTION.
2603 //
2604 // 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
2605 //WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
2606 //REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
2607 //INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
2608 //OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
2609 //TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
2610 //YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
2611 //PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
2612 //POSSIBILITY OF SUCH DAMAGES.
2613 //
2614 // END OF TERMS AND CONDITIONS
2615 //------------------------------------------------------------------------
2616 //$Log: cc_kt1_auth_php.c,v $
2617 //Revision 1.11 2009/11/04 16:27:11 dashley
2618 //Information about how to work around missing "libcrypto.so.4" added.
2619 //Only comments were changed.
2620 //
2621 //Revision 1.10 2009/11/04 15:38:54 dashley
2622 //Contact information, copyright, and one or two technical details in
2623 //comments updated. Changes were to comments only.
2624 //
2625 //Revision 1.9 2007/05/23 18:20:21 dashley
2626 //Cosmetic edits.
2627 //
2628 //Revision 1.8 2007/05/23 17:42:12 dashley
2629 //Addition of GPL text.
2630 //
2631 //Revision 1.7 2007/05/23 17:24:54 dashley
2632 //Safety checkin before trying to append the GPL using curl.
2633 //
2634 //Revision 1.6 2007/05/20 04:13:51 dashley
2635 //Edits.
2636 //
2637 //Revision 1.5 2007/05/20 03:47:37 dashley
2638 //Edits.
2639 //
2640 //End of $RCSfile: cc_kt1_auth_php.c,v $
2641 //------------------------------------------------------------------------

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25