diff options
| author | Miro Jurisic <meeroh@mit.edu> | 1999-05-27 20:48:41 +0000 |
|---|---|---|
| committer | Miro Jurisic <meeroh@mit.edu> | 1999-05-27 20:48:41 +0000 |
| commit | bcbbc106a28254cb10acdb88a3d0c90e1799d184 (patch) | |
| tree | 5fae5eb322a14ad4f471e57864194ba7d9542ae7 /src/mac/gss-sample | |
| parent | 0e6789171f43dd5c029aa76eb61050a51c8da9d4 (diff) | |
Removed metric buttload of old Mac crap that hasn't been used for years
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11480 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/mac/gss-sample')
| -rw-r--r-- | src/mac/gss-sample/ChangeLog | 10 | ||||
| -rw-r--r-- | src/mac/gss-sample/gss-client.c | 463 | ||||
| -rw-r--r-- | src/mac/gss-sample/gss-misc.c | 360 | ||||
| -rw-r--r-- | src/mac/gss-sample/gss-sample.sit.hqx | 48 | ||||
| -rw-r--r-- | src/mac/gss-sample/gss.h | 88 |
5 files changed, 0 insertions, 969 deletions
diff --git a/src/mac/gss-sample/ChangeLog b/src/mac/gss-sample/ChangeLog deleted file mode 100644 index 9975f8a92..000000000 --- a/src/mac/gss-sample/ChangeLog +++ /dev/null @@ -1,10 +0,0 @@ -Fri Nov 22 15:51:55 1996 unknown <bjaspan@mit.edu> - - * gss-client.c (connect_to_server): use sizeof instead of h_length - to determine number of bytes of addr to copy from DNS response - [krb5-misc/211] - - -Thu 26 12:00:00 1995 John Rivlin <jrivlin@fusion.com> - - * Created GSS Sample program diff --git a/src/mac/gss-sample/gss-client.c b/src/mac/gss-sample/gss-client.c deleted file mode 100644 index b2be7c84c..000000000 --- a/src/mac/gss-sample/gss-client.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright 1994 by OpenVision Technologies, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appears in all copies and - * that both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of OpenVision not be used - * in advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. OpenVision makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#define GSSAPI_V2 - -#include "gss.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -usage() -{ - fprintf(stderr, "Usage: gss-client [-port port] [-v2] host service msg\r"); - exit(1); -} - -int main(argc, argv) - int argc; - char **argv; -{ - char *service_name, *server_host, *msg; - u_short port = 4444; - int v2 = 0; - - argc = ccommand(&argv); - - /* Parse arguments. */ - argc--; argv++; - while (argc) { - if (strcmp(*argv, "-port") == 0) { - argc--; argv++; - if (!argc) usage(); - port = atoi(*argv); - } else if (strcmp(*argv, "-v2") == 0) { - v2 = 1; - } else - break; - argc--; argv++; - } - if (argc != 3) - usage(); - - server_host = *argv++; - service_name = *argv++; - msg = *argv++; - - if (call_server(server_host, port, v2, service_name, msg) < 0) - exit(1); - - return 0; -} - -/* - * Function: call_server - * - * Purpose: Call the "sign" service. - * - * Arguments: - * - * host (r) the host providing the service - * port (r) the port to connect to on host - * service_name (r) the GSS-API service name to authenticate to - * msg (r) the message to have "signed" - * - * Returns: 0 on success, -1 on failure - * - * Effects: - * - * call_server opens a TCP connection to <host:port> and establishes a - * GSS-API context with service_name over the connection. It then - * seals msg in a GSS-API token with gss_seal, sends it to the server, - * reads back a GSS-API signature block for msg from the server, and - * verifies it with gss_verify. -1 is returned if any step fails, - * otherwise 0 is returned. - */ -int call_server(char *host, u_short port, int dov2, char *service_name, char *msg) -{ - gss_ctx_id_t context; - gss_buffer_desc in_buf, out_buf, context_token; - int state; - SOCKET s; - OM_uint32 maj_stat, min_stat; - gss_name_t src_name, targ_name; - gss_buffer_desc sname, tname; - OM_uint32 lifetime; - gss_OID mechanism; - int is_local; -#ifdef GSSAPI_V2 - OM_uint32 context_flags; - int is_open; - gss_qop_t qop_state; - gss_OID_set mech_names; - gss_buffer_desc oid_name; -#else /* GSSAPI_V2 */ - int context_flags; -#endif /* GSSAPI_V2 */ - - - /* Open connection */ - if ((s = connect_to_server(host, port)) == (SOCKET) -1) - return -1; - - /* Establish context */ - if (client_establish_context(s, service_name, &context) < 0) - return -1; - -#ifdef GSSAPI_V2 - if (dov2) { - /* - * Attempt to save and then restore the context. - */ - maj_stat = gss_export_sec_context(&min_stat, - &context, - &context_token); - if (maj_stat != GSS_S_COMPLETE) { - display_status("exporting context", maj_stat, min_stat); - return -1; - } - maj_stat = gss_import_sec_context(&min_stat, - &context_token, - &context); - if (maj_stat != GSS_S_COMPLETE) { - display_status("importing context", maj_stat, min_stat); - return -1; - } - (void) gss_release_buffer(&min_stat, &context_token); - } -#endif /* GSSAPI_V2 */ - - /* Get context information */ - maj_stat = gss_inquire_context(&min_stat, context, - &src_name, &targ_name, &lifetime, - &mechanism, &context_flags, - &is_local -#ifdef GSSAPI_V2 - , &is_open -#endif /* GSSAPI_V2 */ - ); - if (maj_stat != GSS_S_COMPLETE) { - display_status("inquiring context", maj_stat, min_stat); - return -1; - } - - maj_stat = gss_display_name(&min_stat, src_name, &sname, - (gss_OID *) NULL); - if (maj_stat != GSS_S_COMPLETE) { - display_status("displaying context", maj_stat, min_stat); - return -1; - } - maj_stat = gss_display_name(&min_stat, targ_name, &tname, - (gss_OID *) NULL); - if (maj_stat != GSS_S_COMPLETE) { - display_status("displaying context", maj_stat, min_stat); - return -1; - } - fprintf(stderr, "\"%s\" to \"%s\"\r lifetime %d, flags %x, %s", - sname.value, tname.value, lifetime, context_flags, - (is_local) ? "locally initiated" : "remotely initiated"); -#ifdef GSSAPI_V2 - fprintf(stderr, " %s", (is_open) ? "open" : "closed"); -#endif /* GSSAPI_V2 */ - fprintf(stderr, "\r"); - - (void) gss_release_name(&min_stat, &src_name); - (void) gss_release_name(&min_stat, &targ_name); - (void) gss_release_buffer(&min_stat, &sname); - (void) gss_release_buffer(&min_stat, &tname); - -#ifdef GSSAPI_V2 - if (dov2) { - size_t i; - - /* Now get the names supported by the mechanism */ - maj_stat = gss_inquire_names_for_mech(&min_stat, - mechanism, - &mech_names); - if (maj_stat != GSS_S_COMPLETE) { - display_status("inquiring mech names", maj_stat, min_stat); - return -1; - } - - maj_stat = gss_oid_to_str(&min_stat, - mechanism, - &oid_name); - if (maj_stat != GSS_S_COMPLETE) { - display_status("converting oid->string", maj_stat, min_stat); - return -1; - } - fprintf(stderr, "Mechanism %s supports %d names\r", - oid_name.value, mech_names->count); - (void) gss_release_buffer(&min_stat, &oid_name); - for (i=0; i<mech_names->count; i++) { - gss_OID tmpoid; - int is_present; - - maj_stat = gss_oid_to_str(&min_stat, - &mech_names->elements[i], - &oid_name); - if (maj_stat != GSS_S_COMPLETE) { - display_status("converting oid->string", maj_stat, min_stat); - return -1; - } - fprintf(stderr, "%d: %s\r", i, oid_name.value); - - maj_stat = gss_str_to_oid(&min_stat, - &oid_name, - &tmpoid); - if (maj_stat != GSS_S_COMPLETE) { - display_status("converting string->oid", maj_stat, min_stat); - return -1; - } - - maj_stat = gss_test_oid_set_member(&min_stat, - tmpoid, - mech_names, - &is_present); - if (maj_stat != GSS_S_COMPLETE) { - display_status("testing oid presence", maj_stat, min_stat); - return -1; - } - if (!is_present) { - fprintf(stderr, "%s is not present in list?\r", - oid_name.value); - } - (void) gss_release_oid(&min_stat, &tmpoid); - (void) gss_release_buffer(&min_stat, &oid_name); - } - - (void) gss_release_oid_set(&min_stat, &mech_names); - (void) gss_release_oid(&min_stat, &mechanism); - } -#endif /* GSSAPI_V2 */ - - /* Seal the message */ - in_buf.value = msg; - in_buf.length = strlen(msg) + 1; -#ifdef GSSAPI_V2 - if (dov2) - maj_stat = gss_wrap(&min_stat, context, 1, GSS_C_QOP_DEFAULT, - &in_buf, &state, &out_buf); - else -#endif /* GSSAPI_V2 */ - maj_stat = gss_seal(&min_stat, context, 1, GSS_C_QOP_DEFAULT, - &in_buf, &state, &out_buf); - if (maj_stat != GSS_S_COMPLETE) { - display_status("sealing message", maj_stat, min_stat); - return -1; - } else if (! state) { - fprintf(stderr, "Warning! Message not encrypted.\r"); - } - - /* Send to server */ - if (send_token(s, &out_buf) < 0) - return -1; - (void) gss_release_buffer(&min_stat, &out_buf); - - /* Read signature block into out_buf */ - if (recv_token(s, &out_buf) < 0) - return -1; - - /* Verify signature block */ -#ifdef GSSAPI_V2 - if (dov2) - maj_stat = gss_verify_mic(&min_stat, context, &in_buf, - &out_buf, &qop_state); - else -#endif /* GSSAPI_V2 */ - maj_stat = gss_verify(&min_stat, context, &in_buf, &out_buf, &state); - if (maj_stat != GSS_S_COMPLETE) { - display_status("verifying signature", maj_stat, min_stat); - return -1; - } - (void) gss_release_buffer(&min_stat, &out_buf); - - printf("Signature verified.\r"); - - /* Delete context */ - maj_stat = gss_delete_sec_context(&min_stat, &context, &out_buf); - if (maj_stat != GSS_S_COMPLETE) { - display_status("deleting context", maj_stat, min_stat); - return -1; - } - (void) gss_release_buffer(&min_stat, &out_buf); - - closesocket(s); - - return 0; -} - -/* - * Function: connect_to_server - * - * Purpose: Opens a TCP connection to the name host and port. - * - * Arguments: - * - * host (r) the target host name - * port (r) the target port, in host byte order - * - * Returns: the established socket file desciptor, or -1 on failure - * - * Effects: - * - * The host name is resolved with gethostbyname(), and the socket is - * opened and connected. If an error occurs, an error message is - * displayed and -1 is returned. - */ -SOCKET connect_to_server(char *host, u_short port) -{ - struct sockaddr_in saddr; - struct hostent *hp; - SOCKET s; - - if ((hp = gethostbyname(host)) == NULL) { - fprintf(stderr, "Unknown host: %s\r", host); - return (SOCKET) -1; - } - - saddr.sin_family = hp->h_addrtype; - memcpy((char *)&saddr.sin_addr, hp->h_addr, sizeof(saddr.sin_addr)); - saddr.sin_port = htons(port); - - if ((s = socket(AF_INET, SOCK_STREAM, 0)) == (SOCKET) -1) { - perror("creating socket"); - return (SOCKET) -1; - } - if (connect(s, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { - perror("connecting to server"); - return (SOCKET) -1; - } - return s; -} - - -/* - * Function: client_establish_context - * - * Purpose: establishes a GSS-API context with a specified service and - * returns the context handle - * - * Arguments: - * - * s (r) an established TCP connection to the service - * service_name (r) the ASCII service name of the service - * context (w) the established GSS-API context - * - * Returns: 0 on success, -1 on failure - * - * Effects: - * - * service_name is imported as a GSS-API name and a GSS-API context is - * established with the corresponding service; the service should be - * listening on the TCP connection s. The default GSS-API mechanism - * is used, and mutual authentication and replay detection are - * requested. - * - * If successful, the context handle is returned in context. If - * unsuccessful, the GSS-API error messages are displayed on stderr - * and -1 is returned. - */ -int client_establish_context(SOCKET s, char *service_name, gss_ctx_id_t *gss_context) -{ - gss_buffer_desc send_tok, recv_tok, *token_ptr; - gss_name_t target_name; - OM_uint32 maj_stat, min_stat; - - /* - * Import the name into target_name. Use send_tok to save - * local variable space. - */ - send_tok.value = service_name; - send_tok.length = strlen(service_name) + 1; - maj_stat = gss_import_name(&min_stat, &send_tok, - (gss_OID) gss_nt_service_name, &target_name); - if (maj_stat != GSS_S_COMPLETE) { - display_status("parsing name", maj_stat, min_stat); - return -1; - } - - /* - * Perform the context-establishement loop. - * - * On each pass through the loop, token_ptr points to the token - * to send to the server (or GSS_C_NO_BUFFER on the first pass). - * Every generated token is stored in send_tok which is then - * transmitted to the server; every received token is stored in - * recv_tok, which token_ptr is then set to, to be processed by - * the next call to gss_init_sec_context. - * - * GSS-API guarantees that send_tok's length will be non-zero - * if and only if the server is expecting another token from us, - * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if - * and only if the server has another token to send us. - */ - - token_ptr = GSS_C_NO_BUFFER; - *gss_context = GSS_C_NO_CONTEXT; - - do { - maj_stat = - gss_init_sec_context(&min_stat, - GSS_C_NO_CREDENTIAL, - gss_context, - target_name, - GSS_C_NULL_OID, - GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG, - 0, - NULL, /* no channel bindings */ - token_ptr, - NULL, /* ignore mech type */ - &send_tok, - NULL, /* ignore ret_flags */ - NULL); /* ignore time_rec */ - - if (token_ptr != GSS_C_NO_BUFFER) - (void) gss_release_buffer(&min_stat, &recv_tok); - - if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) { - display_status("initializing context", maj_stat, min_stat); - (void) gss_release_name(&min_stat, &target_name); - return -1; - } - - if (send_tok.length != 0) { - if (send_token(s, &send_tok) < 0) { - (void) gss_release_buffer(&min_stat, &send_tok); - (void) gss_release_name(&min_stat, &target_name); - return -1; - } - } - (void) gss_release_buffer(&min_stat, &send_tok); - - if (maj_stat == GSS_S_CONTINUE_NEEDED) { - if (recv_token(s, &recv_tok) < 0) { - (void) gss_release_name(&min_stat, &target_name); - return -1; - } - token_ptr = &recv_tok; - } - } while (maj_stat == GSS_S_CONTINUE_NEEDED); - - (void) gss_release_name(&min_stat, &target_name); - return 0; -} diff --git a/src/mac/gss-sample/gss-misc.c b/src/mac/gss-sample/gss-misc.c deleted file mode 100644 index b47cf8927..000000000 --- a/src/mac/gss-sample/gss-misc.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - - * Copyright 1994 by OpenVision Technologies, Inc. - - * - - * Permission to use, copy, modify, distribute, and sell this software - - * and its documentation for any purpose is hereby granted without fee, - - * provided that the above copyright notice appears in all copies and - - * that both that copyright notice and this permission notice appear in - - * supporting documentation, and that the name of OpenVision not be used - - * in advertising or publicity pertaining to distribution of the software - - * without specific, written prior permission. OpenVision makes no - - * representations about the suitability of this software for any - - * purpose. It is provided "as is" without express or implied warranty. - - * - - * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - - * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR - - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - - * PERFORMANCE OF THIS SOFTWARE. - - */ - - - -#include "gss.h" - -#include <string.h> - -#include <errno.h> - -#include <stdio.h> - -#include <stdlib.h> - - - -/* - - * Function: send_token - - * - - * Purpose: Writes a token to a file descriptor. - - * - - * Arguments: - - * - - * s (r) an open file descriptor - - * tok (r) the token to write - - * - - * Returns: 0 on success, -1 on failure - - * - - * Effects: - - * - - * send_token writes the token length (as a network long) and then the - - * token data to the file descriptor s. It returns 0 on success, and - - * -1 if an error occurs or if it could not write all the data. - - */ - -int send_token(SOCKET s, gss_buffer_t tok) { - - size_t ret; - - - - ret = send(s, (char *) &tok->length, 4, 0); - - - - if (ret < 0) { - - fprintf(stderr, "Error sending token length\r"); - - return -1; - - } - - else if (ret != 4) { - - fprintf(stderr, "sending token length: %d of %d bytes written\r", ret, 4); - - return -1; - - } - - - - ret = send(s, tok->value, tok->length, 0); - - - - if (ret < 0) { - - fprintf(stderr, "Error sending data\r"); - - return -1; - - } - - else if (ret != tok->length) { - - fprintf(stderr, "sending token data: %d of %d bytes written\r", ret, tok->length); - - return -1; - - } - - - - return 0; - - - -} /* send_token */ - - - - - -/* - - * Function: recv_token - - * - - * Purpose: Reads a token from a file descriptor. - - * - - * Arguments: - - * - - * s (r) an open file descriptor - - * tok (w) the read token - - * - - * Returns: 0 on success, -1 on failure - - * - - * Effects: - - * - - * recv_token reads the token length (as a network long), allocates - - * memory to hold the data, and then reads the token data from the - - * file descriptor s. It blocks to read the length and data, if - - * necessary. On a successful return, the token should be freed with - - * gss_release_buffer. It returns 0 on success, and -1 if an error - - * occurs or if it could not read all the data. - - */ - -int - -recv_token (SOCKET s, gss_buffer_t tok) { - - int ret; - - unsigned long len; - - - - ret = recv(s, (char *) &len, 4, 0); - - - - if (ret < 0) { - - fprintf(stderr, "Error reading token length\r"); - - return -1; - - } - - else if (ret != 4) { - - fprintf(stderr, "Error reading token length: %d of %d bytes read\r", ret, 4); - - return -1; - - } - - - - tok->length = (size_t) len; - - - - tok->value = (char *) malloc(tok->length); - - - - if (tok->value == NULL) { - - fprintf(stderr, "Out of memory allocating token data\r"); - - return -1; - - } - - - - ret = recv (s, (char *) tok->value, tok->length, 0); - - - - if (ret < 0) { - - fprintf(stderr, "Error reading token data\r"); - - free(tok->value); - - return -1; - - } - - - - return 0; - -} /* recv_token */ - - - - - -/* - - * Function: display_status - - * - - * Purpose: displays GSS-API messages - - * - - * Arguments: - - * - - * msg a string to be displayed with the message - - * maj_stat the GSS-API major status code - - * min_stat the GSS-API minor status code - - * - - * Effects: - - * - - * The GSS-API messages associated with maj_stat and min_stat are - - * displayed on stderr, each preceeded by "GSS-API error <msg>: " and - - * followed by a newline. - - */ - -void - -display_status (char *msg, OM_uint32 maj_stat, OM_uint32 min_stat) { - - display_status_1(msg, maj_stat, GSS_C_GSS_CODE); - - display_status_1(msg, min_stat, GSS_C_MECH_CODE); - -} - - - -static void - -display_status_1(char *m, OM_uint32 code, int type) { - - OM_uint32 maj_stat, min_stat; - - gss_buffer_desc msg; - - #ifdef GSSAPI_V2 - - OM_uint32 msg_ctx; - - #else /* GSSAPI_V2 */ - - int msg_ctx; - - #endif /* GSSAPI_V2 */ - - - - msg_ctx = 0; - - while (1) { - - maj_stat = gss_display_status( - - &min_stat, code, type, GSS_C_NULL_OID, &msg_ctx, &msg); - - - - fprintf (stderr, "GSS-API error %s: %s\r", m, (char *)msg.value); - - - - (void) gss_release_buffer(&min_stat, &msg); - - - - if (!msg_ctx) - - break; - - } - -} /* display_status */ - diff --git a/src/mac/gss-sample/gss-sample.sit.hqx b/src/mac/gss-sample/gss-sample.sit.hqx deleted file mode 100644 index 2927c3184..000000000 --- a/src/mac/gss-sample/gss-sample.sit.hqx +++ /dev/null @@ -1,48 +0,0 @@ -(This file must be converted with BinHex 4.0) -:$QGcFbecB@e`E'8ZFfPd!&0*9%46593K!!!!!!G*!!!"4V`K8dP8)3!#!!!(5A* --BA8#!3!!!"B!!!d0$%G68b"6B@e`E'8ZYA0bB`!!!!!!!!!!!!!!!!!!!!$I'J! -!!!!!!!!!!!!!!!!!!!!!!!!!"T!!!!!!!2rrrrp069"568e$3`%!V$aa3kb3!*a -+!!!*m3!!#U)!!!)e!!!$eD"kNV-!!!!!!!!50#0%$L)Uq`C4+5ScT300hITKF$j -mZT@4#)Y)kBc#IAqDGT+61M[$hCfGJB#$FQr3Y(I`EJH2,0X8)#UrMFMpYaB"!e" -Z*bT'CFE6IDpqD1,9S*JFF&HPm`50Sa-cDlN1cNZ4D2Gdp%H+TZGb"82F$!Y6@pJ -!#pY[B3-&aPaKUe"XUffBBQd&ICkFP[Cc9(5!0Qb3!&ACP#9&hXcrr4$mrYfi`6! -PhIar5%[k09a2bkTNrPIlq(BLd6qpC,c8F0JDGl'5*U,eqrpI`IhcBi4c#C[Sf1e -`1Xmpb[HPSVp6C3@,HFED&4k'h[qrIH84i'9LUM8PRCSUaE3r"X&6,C8l[ZJF(ZN -l(ed1V!@&LahS1"&X13FHKB,b2EclEl6D'#UfjIpqZD!#9G(QIBV2Reaj@()T1G' -4bb&XbGkA3483ip+P5f8eTQ6MI'QIhVY`U@H-S&Zk9*&lG8QAZE(d1"!"68`DKT5 -4PbDjbR8jYR6#-4Ve)(-S1#-Qa9,m'+IDjQ!1UT(d@"`ra"14a6dRq$R2r&XY@p! -6c!4SaDUb[bI&qY51R[Vrbj,Va2cp(iArm'-(0p*hR4-FV`YSbeDL5&SJp)c&(UV -MP`EcRE[D*S9!-6R'jImS'%Eq+"c*re%iqArlSk!Gqk0!6`h1GNrr,R$2@KJV-1N -D9ePB['f3!'*Q#q-YE+U&+5eXYS@T,B`Q60`@GXR#pJK-CCmX#J[c'jd4jJl,AT1 -9`8X#-i4eE512Q3aj@f90I4m!!!X!YrCqjZ8PNc$#MM$*d`JMJl8MaeC#Mc#6X*- -``XiMc#6d#205GREN+'&(MTeiLNqbRS3kL1