2 * Copyright (c) 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of KTH nor the names of its contributors may be
18 * used to endorse or promote products derived from this software without
19 * specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 enum handle_type
{ handle_context
, handle_cred
};
45 enum handle_type type
;
52 krb5_storage
*logging
;
55 struct handle
*handles
;
56 struct sockaddr_storage sa
;
58 char servername
[MAXHOSTNAMELEN
];
62 static char *targetname
;
70 logmessage(struct client
*c
, const char *file
, unsigned int lineno
,
71 int level
, const char *fmt
, ...)
79 ret
= vasprintf(&message
, fmt
, ap
);
82 errx(1, "out of memory");
85 fprintf(logfile
, "%s:%u: %d %s\n", file
, lineno
, level
, message
);
88 if (krb5_store_int32(c
->logging
, eLogInfo
) != 0)
89 errx(1, "krb5_store_int32: log level");
90 if (krb5_store_string(c
->logging
, file
) != 0)
91 errx(1, "krb5_store_string: filename");
92 if (krb5_store_int32(c
->logging
, lineno
) != 0)
93 errx(1, "krb5_store_string: filename");
94 if (krb5_store_string(c
->logging
, message
) != 0)
95 errx(1, "krb5_store_string: message");
96 if (krb5_ret_int32(c
->logging
, &ackid
) != 0)
97 errx(1, "krb5_ret_int32: ackid");
107 add_handle(struct client
*c
, enum handle_type type
, void *data
)
111 h
= ecalloc(1, sizeof(*h
));
113 h
->idx
= ++c
->nHandle
;
116 h
->next
= c
->handles
;
123 del_handle(struct handle
**h
, int32_t idx
)
131 if ((*h
)->idx
== idx
) {
132 struct handle
*p
= *h
;
135 case handle_context
: {
136 gss_ctx_id_t c
= p
->ptr
;
137 gss_delete_sec_context(&min_stat
, &c
, NULL
);
140 gss_cred_id_t c
= p
->ptr
;
141 gss_release_cred(&min_stat
, &c
);
149 errx(1, "tried to delete an unexisting handle");
153 find_handle(struct handle
*h
, int32_t idx
, enum handle_type type
)
162 errx(1, "monger switched type on handle!");
171 convert_gss_to_gsm(OM_uint32 maj_stat
)
176 case GSS_S_CONTINUE_NEEDED
:
177 return GSMERR_CONTINUE_NEEDED
;
178 case GSS_S_DEFECTIVE_TOKEN
:
179 return GSMERR_INVALID_TOKEN
;
181 return GSMERR_AP_MODIFIED
;
188 convert_krb5_to_gsm(krb5_error_code ret
)
203 acquire_cred(struct client
*c
,
204 krb5_principal principal
,
205 krb5_get_init_creds_opt
*opt
,
212 OM_uint32 maj_stat
, min_stat
;
216 krb5_get_init_creds_opt_set_forwardable (opt
, 1);
217 krb5_get_init_creds_opt_set_renew_life (opt
, 3600 * 24 * 30);
219 memset(&cred
, 0, sizeof(cred
));
221 ret
= krb5_get_init_creds_password (context
,
231 logmessage(c
, __FILE__
, __LINE__
, 0,
232 "krb5_get_init_creds failed: %d", ret
);
233 return convert_krb5_to_gsm(ret
);
236 ret
= krb5_cc_new_unique(context
, "MEMORY", NULL
, &id
);
238 krb5_err (context
, 1, ret
, "krb5_cc_initialize");
240 ret
= krb5_cc_initialize (context
, id
, cred
.client
);
242 krb5_err (context
, 1, ret
, "krb5_cc_initialize");
244 ret
= krb5_cc_store_cred (context
, id
, &cred
);
246 krb5_err (context
, 1, ret
, "krb5_cc_store_cred");
248 krb5_free_cred_contents (context
, &cred
);
250 maj_stat
= gss_krb5_import_cred(&min_stat
,
255 krb5_cc_close(context
, id
);
257 logmessage(c
, __FILE__
, __LINE__
, 0,
258 "krb5 import creds failed with: %d", maj_stat
);
259 return convert_gss_to_gsm(maj_stat
);
262 *handle
= add_handle(c
, handle_cred
, gcred
);
272 #define HandleOP(h) \
273 handle##h(enum gssMaggotOp op, struct client *c)
280 HandleOP(GetVersionInfo
)
282 put32(c
, GSSMAGGOTPROTOCOL
);
283 errx(1, "GetVersionInfo");
289 struct handle
*h
= c
->handles
;
298 logmessage(c
, __FILE__
, __LINE__
, 0,
299 "Did not toast all resources: %d", i
);
304 HandleOP(InitContext
)
306 OM_uint32 maj_stat
, min_stat
, ret_flags
;
307 int32_t hContext
, hCred
, flags
;
308 krb5_data target_name
, in_token
;
309 int32_t new_context_id
= 0, gsm_error
= 0;
310 krb5_data out_token
= { 0 , NULL
};
314 gss_name_t gss_target_name
;
315 gss_buffer_desc input_token
;
316 gss_buffer_desc output_token
= {0, 0};
317 gss_OID oid
= GSS_C_NO_OID
;
318 gss_buffer_t input_token_ptr
= GSS_C_NO_BUFFER
;
323 retdata(c
, target_name
);
324 retdata(c
, in_token
);
326 logmessage(c
, __FILE__
, __LINE__
, 0,
327 "targetname: <%.*s>", (int)target_name
.length
,
328 (char *)target_name
.data
);
330 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
333 creds
= find_handle(c
->handles
, hCred
, handle_cred
);
337 input_token
.length
= target_name
.length
;
338 input_token
.value
= target_name
.data
;
340 maj_stat
= gss_import_name(&min_stat
,
342 GSS_KRB5_NT_PRINCIPAL_NAME
,
344 if (GSS_ERROR(maj_stat
)) {
345 logmessage(c
, __FILE__
, __LINE__
, 0,
346 "import name creds failed with: %d", maj_stat
);
347 gsm_error
= convert_gss_to_gsm(maj_stat
);
353 if (in_token
.length
) {
354 input_token
.length
= in_token
.length
;
355 input_token
.value
= in_token
.data
;
356 input_token_ptr
= &input_token
;
358 krb5_errx(context
, 1, "initcreds, context NULL, but not first req");
360 input_token
.length
= 0;
361 input_token
.value
= NULL
;
363 krb5_errx(context
, 1, "initcreds, context not NULL, but first req");
366 if ((flags
& GSS_C_DELEG_FLAG
) != 0)
367 logmessage(c
, __FILE__
, __LINE__
, 0, "init_sec_context delegating");
368 if ((flags
& GSS_C_DCE_STYLE
) != 0)
369 logmessage(c
, __FILE__
, __LINE__
, 0, "init_sec_context dce-style");
371 maj_stat
= gss_init_sec_context(&min_stat
,
384 if (GSS_ERROR(maj_stat
)) {
386 del_handle(&c
->handles
, hContext
);
388 logmessage(c
, __FILE__
, __LINE__
, 0,
389 "gss_init_sec_context returns code: %d/%d",
392 if (input_token
.length
== 0)
393 new_context_id
= add_handle(c
, handle_context
, ctx
);
395 new_context_id
= hContext
;
398 gsm_error
= convert_gss_to_gsm(maj_stat
);
400 if (output_token
.length
) {
401 out_token
.data
= output_token
.value
;
402 out_token
.length
= output_token
.length
;
406 logmessage(c
, __FILE__
, __LINE__
, 0,
407 "InitContext return code: %d", gsm_error
);
409 put32(c
, new_context_id
);
411 putdata(c
, out_token
);
413 gss_release_name(&min_stat
, &gss_target_name
);
414 if (output_token
.length
)
415 gss_release_buffer(&min_stat
, &output_token
);
416 krb5_data_free(&in_token
);
417 krb5_data_free(&target_name
);
423 HandleOP(AcceptContext
)
425 OM_uint32 maj_stat
, min_stat
, ret_flags
;
426 int32_t hContext
, deleg_hcred
, flags
;
428 int32_t new_context_id
= 0, gsm_error
= 0;
429 krb5_data out_token
= { 0 , NULL
};
432 gss_cred_id_t deleg_cred
= GSS_C_NO_CREDENTIAL
;
433 gss_buffer_desc input_token
, output_token
;
437 retdata(c
, in_token
);
439 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
443 if (in_token
.length
) {
444 input_token
.length
= in_token
.length
;
445 input_token
.value
= in_token
.data
;
447 input_token
.length
= 0;
448 input_token
.value
= NULL
;
451 maj_stat
= gss_accept_sec_context(&min_stat
,
455 GSS_C_NO_CHANNEL_BINDINGS
,
462 if (GSS_ERROR(maj_stat
)) {
464 del_handle(&c
->handles
, hContext
);
465 logmessage(c
, __FILE__
, __LINE__
, 0,
466 "gss_accept_sec_context returns code: %d/%d",
471 new_context_id
= add_handle(c
, handle_context
, ctx
);
473 new_context_id
= hContext
;
475 if (output_token
.length
) {
476 out_token
.data
= output_token
.value
;
477 out_token
.length
= output_token
.length
;
479 if ((ret_flags
& GSS_C_DCE_STYLE
) != 0)
480 logmessage(c
, __FILE__
, __LINE__
, 0, "accept_sec_context dce-style");
481 if ((ret_flags
& GSS_C_DELEG_FLAG
) != 0) {
482 deleg_hcred
= add_handle(c
, handle_cred
, deleg_cred
);
483 logmessage(c
, __FILE__
, __LINE__
, 0,
484 "accept_context delegated handle: %d", deleg_hcred
);
486 gss_release_cred(&min_stat
, &deleg_cred
);
491 gsm_error
= convert_gss_to_gsm(maj_stat
);
493 put32(c
, new_context_id
);
495 putdata(c
, out_token
);
496 put32(c
, deleg_hcred
);
498 if (output_token
.length
)
499 gss_release_buffer(&min_stat
, &output_token
);
500 krb5_data_free(&in_token
);
506 HandleOP(ToastResource
)
511 logmessage(c
, __FILE__
, __LINE__
, 0, "toasting %d", handle
);
512 del_handle(&c
->handles
, handle
);
519 HandleOP(AcquireCreds
)
521 char *name
, *password
;
522 int32_t gsm_error
, flags
, handle
= 0;
523 krb5_principal principal
= NULL
;
524 krb5_get_init_creds_opt
*opt
= NULL
;
528 retstring(c
, password
);
531 logmessage(c
, __FILE__
, __LINE__
, 0,
532 "username: %s password: %s", name
, password
);
534 ret
= krb5_parse_name(context
, name
, &principal
);
536 gsm_error
= convert_krb5_to_gsm(ret
);
540 ret
= krb5_get_init_creds_opt_alloc (context
, &opt
);
542 krb5_err(context
, 1, ret
, "krb5_get_init_creds_opt_alloc");
544 krb5_get_init_creds_opt_set_pa_password(context
, opt
, password
, NULL
);
546 gsm_error
= acquire_cred(c
, principal
, opt
, &handle
);
549 logmessage(c
, __FILE__
, __LINE__
, 0,
550 "AcquireCreds handle: %d return code: %d", handle
, gsm_error
);
553 krb5_get_init_creds_opt_free (context
, opt
);
555 krb5_free_principal(context
, principal
);
568 OM_uint32 maj_stat
, min_stat
;
569 int32_t hContext
, flags
, seqno
;
572 gss_buffer_desc input_token
, output_token
;
579 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
581 errx(1, "sign: reference to unknown context");
583 input_token
.length
= token
.length
;
584 input_token
.value
= token
.data
;
586 maj_stat
= gss_get_mic(&min_stat
, ctx
, 0, &input_token
,
588 if (maj_stat
!= GSS_S_COMPLETE
)
589 errx(1, "gss_get_mic failed");
591 krb5_data_free(&token
);
593 token
.data
= output_token
.value
;
594 token
.length
= output_token
.length
;
596 put32(c
, 0); /* XXX fix gsm_error */
599 gss_release_buffer(&min_stat
, &output_token
);
607 OM_uint32 maj_stat
, min_stat
;
608 int32_t hContext
, flags
, seqno
;
611 gss_buffer_desc msg_token
, mic_token
;
616 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
618 errx(1, "verify: reference to unknown context");
624 msg_token
.length
= msg
.length
;
625 msg_token
.value
= msg
.data
;
629 mic_token
.length
= mic
.length
;
630 mic_token
.value
= mic
.data
;
632 maj_stat
= gss_verify_mic(&min_stat
, ctx
, &msg_token
,
634 if (maj_stat
!= GSS_S_COMPLETE
)
635 errx(1, "gss_verify_mic failed");
637 krb5_data_free(&mic
);
638 krb5_data_free(&msg
);
640 put32(c
, 0); /* XXX fix gsm_error */
646 HandleOP(GetVersionAndCapabilities
)
648 int32_t cap
= HAS_MONIKER
;
649 char name
[256] = "unknown", *str
;
653 cap
|= ISSERVER
; /* is server */
658 if (uname(&ut
) == 0) {
659 snprintf(name
, sizeof(name
), "%s-%s-%s",
660 ut
.sysname
, ut
.version
, ut
.machine
);
665 ret
= asprintf(&str
, "gssmask %s %s", PACKAGE_STRING
, name
);
667 errx(1, "out of memory");
669 put32(c
, GSSMAGGOTPROTOCOL
);
678 HandleOP(GetTargetName
)
681 putstring(c
, targetname
);
688 HandleOP(SetLoggingSocket
)
696 logmessage(c
, __FILE__
, __LINE__
, 0,
697 "logging port on peer is: %d", (int)portnum
);
699 socket_set_port((struct sockaddr
*)(&c
->sa
), htons(portnum
));
701 sock
= socket(((struct sockaddr
*)&c
->sa
)->sa_family
, SOCK_STREAM
, 0);
702 if (sock
== rk_INVALID_SOCKET
)
705 ret
= connect(sock
, (struct sockaddr
*)&c
->sa
, c
->salen
);
707 logmessage(c
, __FILE__
, __LINE__
, 0, "failed connect to log port: %s",
709 rk_closesocket(sock
);
714 krb5_storage_free(c
->logging
);
715 c
->logging
= krb5_storage_from_socket(sock
);
716 rk_closesocket(sock
);
718 krb5_store_int32(c
->logging
, eLogSetMoniker
);
719 store_string(c
->logging
, c
->moniker
);
721 logmessage(c
, __FILE__
, __LINE__
, 0, "logging turned on");
728 HandleOP(ChangePassword
)
730 errx(1, "ChangePassword");
734 HandleOP(SetPasswordSelf
)
736 errx(1, "SetPasswordSelf");
742 OM_uint32 maj_stat
, min_stat
;
743 int32_t hContext
, flags
, seqno
;
746 gss_buffer_desc input_token
, output_token
;
754 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
756 errx(1, "wrap: reference to unknown context");
758 input_token
.length
= token
.length
;
759 input_token
.value
= token
.data
;
761 maj_stat
= gss_wrap(&min_stat
, ctx
, flags
, 0, &input_token
,
762 &conf_state
, &output_token
);
763 if (maj_stat
!= GSS_S_COMPLETE
)
764 errx(1, "gss_wrap failed");
766 krb5_data_free(&token
);
768 token
.data
= output_token
.value
;
769 token
.length
= output_token
.length
;
771 put32(c
, 0); /* XXX fix gsm_error */
774 gss_release_buffer(&min_stat
, &output_token
);
783 OM_uint32 maj_stat
, min_stat
;
784 int32_t hContext
, flags
, seqno
;
787 gss_buffer_desc input_token
, output_token
;
796 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
798 errx(1, "unwrap: reference to unknown context");
800 input_token
.length
= token
.length
;
801 input_token
.value
= token
.data
;
803 maj_stat
= gss_unwrap(&min_stat
, ctx
, &input_token
,
804 &output_token
, &conf_state
, &qop_state
);
806 if (maj_stat
!= GSS_S_COMPLETE
)
807 errx(1, "gss_unwrap failed: %d/%d", maj_stat
, min_stat
);
809 krb5_data_free(&token
);
810 if (maj_stat
== GSS_S_COMPLETE
) {
811 token
.data
= output_token
.value
;
812 token
.length
= output_token
.length
;
817 put32(c
, 0); /* XXX fix gsm_error */
820 if (maj_stat
== GSS_S_COMPLETE
)
821 gss_release_buffer(&min_stat
, &output_token
);
829 return handleWrap(op
, c
);
835 return handleUnwrap(op
, c
);
839 HandleOP(ConnectLoggingService2
)
841 errx(1, "ConnectLoggingService2");
847 putstring(c
, c
->moniker
);
852 HandleOP(CallExtension
)
854 errx(1, "CallExtension");
858 HandleOP(AcquirePKInitCreds
)
862 char fn
[] = "FILE:/tmp/pkcs12-creds-XXXXXXX";
868 fd
= mkstemp(fn
+ 5);
872 net_write(fd
, pfxdata
.data
, pfxdata
.length
);
873 krb5_data_free(&pfxdata
);
876 put32(c
, -1); /* hResource */
877 put32(c
, GSMERR_NOT_SUPPORTED
);
884 OM_uint32 maj_stat
, min_stat
;
885 int32_t hContext
, flags
, bflags
;
886 krb5_data token
, header
, trailer
;
889 int conf_state
, iov_len
;
890 gss_iov_buffer_desc iov
[6];
899 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
901 errx(1, "wrap: reference to unknown context");
903 memset(&iov
, 0, sizeof(iov
));
905 iov_len
= sizeof(iov
)/sizeof(iov
[0]);
907 if (bflags
& WRAP_EXP_ONLY_HEADER
)
908 iov_len
-= 2; /* skip trailer and padding, aka dce-style */
910 iov
[0].type
= GSS_IOV_BUFFER_TYPE_HEADER
| GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE
;
911 if (header
.length
!= 0) {
912 iov
[1].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
913 iov
[1].buffer
.length
= header
.length
;
914 iov
[1].buffer
.value
= header
.data
;
916 iov
[1].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
918 iov
[2].type
= GSS_IOV_BUFFER_TYPE_DATA
;
919 iov
[2].buffer
.length
= token
.length
;
920 iov
[2].buffer
.value
= token
.data
;
921 if (trailer
.length
!= 0) {
922 iov
[3].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
923 iov
[3].buffer
.length
= trailer
.length
;
924 iov
[3].buffer
.value
= trailer
.data
;
926 iov
[3].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
928 iov
[4].type
= GSS_IOV_BUFFER_TYPE_PADDING
| GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE
;
929 iov
[5].type
= GSS_IOV_BUFFER_TYPE_TRAILER
| GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE
;
931 maj_stat
= gss_wrap_iov_length(&min_stat
, ctx
, flags
, 0, &conf_state
,
933 if (maj_stat
!= GSS_S_COMPLETE
)
934 errx(1, "gss_wrap_iov_length failed");
936 maj_stat
= gss_wrap_iov(&min_stat
, ctx
, flags
, 0, &conf_state
,
938 if (maj_stat
!= GSS_S_COMPLETE
)
939 errx(1, "gss_wrap_iov failed");
941 krb5_data_free(&token
);
943 token
.length
= iov
[0].buffer
.length
+ iov
[2].buffer
.length
+ iov
[4].buffer
.length
+ iov
[5].buffer
.length
;
944 token
.data
= malloc(token
.length
);
947 memcpy(p
, iov
[0].buffer
.value
, iov
[0].buffer
.length
);
948 p
+= iov
[0].buffer
.length
;
949 memcpy(p
, iov
[2].buffer
.value
, iov
[2].buffer
.length
);
950 p
+= iov
[2].buffer
.length
;
951 memcpy(p
, iov
[4].buffer
.value
, iov
[4].buffer
.length
);
952 p
+= iov
[4].buffer
.length
;
953 memcpy(p
, iov
[5].buffer
.value
, iov
[5].buffer
.length
);
954 p
+= iov
[5].buffer
.length
;
956 gss_release_iov_buffer(NULL
, iov
, iov_len
);
958 put32(c
, 0); /* XXX fix gsm_error */
970 OM_uint32 maj_stat
, min_stat
;
971 int32_t hContext
, flags
, bflags
;
972 krb5_data token
, header
, trailer
;
974 gss_iov_buffer_desc iov
[3];
975 int conf_state
, iov_len
;
985 iov_len
= sizeof(iov
)/sizeof(iov
[0]);
987 if (bflags
& WRAP_EXP_ONLY_HEADER
)
988 iov_len
-= 1; /* skip trailer and padding, aka dce-style */
990 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
992 errx(1, "unwrap: reference to unknown context");
994 if (header
.length
!= 0) {
995 iov
[0].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
996 iov
[0].buffer
.length
= header
.length
;
997 iov
[0].buffer
.value
= header
.data
;
999 iov
[0].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
1001 iov
[1].type
= GSS_IOV_BUFFER_TYPE_DATA
;
1002 iov
[1].buffer
.length
= token
.length
;
1003 iov
[1].buffer
.value
= token
.data
;
1005 if (trailer
.length
!= 0) {
1006 iov
[2].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
1007 iov
[2].buffer
.length
= trailer
.length
;
1008 iov
[2].buffer
.value
= trailer
.data
;
1010 iov
[2].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
1013 maj_stat
= gss_unwrap_iov(&min_stat
, ctx
, &conf_state
, &qop_state
,
1016 if (maj_stat
!= GSS_S_COMPLETE
)
1017 errx(1, "gss_unwrap failed: %d/%d", maj_stat
, min_stat
);
1019 if (maj_stat
== GSS_S_COMPLETE
) {
1020 token
.data
= iov
[1].buffer
.value
;
1021 token
.length
= iov
[1].buffer
.length
;
1026 put32(c
, 0); /* XXX fix gsm_error */
1037 enum gssMaggotOp op
;
1039 int (*func
)(enum gssMaggotOp
, struct client
*);
1042 #define S(a) { e##a, #a, handle##a }
1044 struct handler handlers
[] = {
1055 S(GetVersionAndCapabilities
),
1057 S(SetLoggingSocket
),
1062 S(ConnectLoggingService2
),
1065 S(AcquirePKInitCreds
),
1076 static struct handler
*
1081 for (i
= 0; i
< sizeof(handlers
)/sizeof(handlers
[0]); i
++)
1082 if (handlers
[i
].op
== op
)
1083 return &handlers
[i
];
1087 static struct client
*
1088 create_client(krb5_socket_t sock
, int port
, const char *moniker
)
1093 c
= ecalloc(1, sizeof(*c
));
1096 c
->moniker
= estrdup(moniker
);
1098 char hostname
[MAXHOSTNAMELEN
];
1099 gethostname(hostname
, sizeof(hostname
));
1100 ret
= asprintf(&c
->moniker
, "gssmask: %s:%d", hostname
, port
);
1106 errx(1, "out of memory");
1109 c
->salen
= sizeof(c
->sa
);
1110 getpeername(sock
, (struct sockaddr
*)&c
->sa
, &c
->salen
);
1112 getnameinfo((struct sockaddr
*)&c
->sa
, c
->salen
,
1113 c
->servername
, sizeof(c
->servername
),
1114 NULL
, 0, NI_NUMERICHOST
);
1117 c
->sock
= krb5_storage_from_socket(sock
);
1118 if (c
->sock
== NULL
)
1119 errx(1, "krb5_storage_from_socket");
1121 rk_closesocket(sock
);
1127 free_client(struct client
*c
)
1130 del_handle(&c
->handles
, c
->handles
->idx
);
1133 krb5_storage_free(c
->sock
);
1135 krb5_storage_free(c
->logging
);
1141 handleServer(void *ptr
)
1143 struct handler
*handler
;
1147 c
= (struct client
*)ptr
;
1153 handler
= find_op(op
);
1154 if (handler
== NULL
) {
1155 logmessage(c
, __FILE__
, __LINE__
, 0,
1156 "op %d not supported", (int)op
);
1160 logmessage(c
, __FILE__
, __LINE__
, 0,
1161 "---> Got op %s from server %s",
1162 handler
->name
, c
->servername
);
1164 if ((handler
->func
)(handler
->op
, c
))
1172 static char *port_str
;
1173 static int version_flag
;
1174 static int help_flag
;
1175 static char *logfile_str
;
1176 static char *moniker_str
;
1178 static int port
= 4711;
1180 struct getargs args
[] = {
1181 { "spn", 0, arg_string
, &targetname
, "This host's SPN",
1182 "service/host@REALM" },
1183 { "port", 'p', arg_string
, &port_str
, "Use this port",
1184 "number-of-service" },
1185 { "logfile", 0, arg_string
, &logfile_str
, "logfile",
1186 "number-of-service" },
1187 { "moniker", 0, arg_string
, &moniker_str
, "nickname",
1189 { "version", 0, arg_flag
, &version_flag
, "Print version",
1191 { "help", 0, arg_flag
, &help_flag
, NULL
,
1198 arg_printusage (args
,
1199 sizeof(args
) / sizeof(args
[0]),
1206 main(int argc
, char **argv
)
1209 krb5_error_code ret
;
1211 setprogname (argv
[0]);
1213 if (getarg (args
, sizeof(args
) / sizeof(args
[0]), argc
, argv
, &optidx
))
1220 print_version (NULL
);
1230 port
= strtol (port_str
, &ptr
, 10);
1231 if (port
== 0 && ptr
== port_str
)
1232 errx (1, "Bad port `%s'", port_str
);
1235 ret
= krb5_init_context(&context
);
1237 errx(1, "Error initializing kerberos: %d", ret
);
1240 const char *lf
= logfile_str
;
1244 logfile
= fopen(lf
, "w");
1245 if (logfile
== NULL
)
1246 err(1, "error opening %s", lf
);
1249 mini_inetd(htons(port
), NULL
);
1250 fprintf(logfile
, "connected\n");
1255 c
= create_client(0, port
, moniker_str
);
1263 krb5_free_context(context
);