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
, output_token
;
316 gss_OID oid
= GSS_C_NO_OID
;
317 gss_buffer_t input_token_ptr
= GSS_C_NO_BUFFER
;
322 retdata(c
, target_name
);
323 retdata(c
, in_token
);
325 logmessage(c
, __FILE__
, __LINE__
, 0,
326 "targetname: <%.*s>", (int)target_name
.length
,
327 (char *)target_name
.data
);
329 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
332 creds
= find_handle(c
->handles
, hCred
, handle_cred
);
336 input_token
.length
= target_name
.length
;
337 input_token
.value
= target_name
.data
;
339 maj_stat
= gss_import_name(&min_stat
,
341 GSS_KRB5_NT_PRINCIPAL_NAME
,
343 if (GSS_ERROR(maj_stat
)) {
344 logmessage(c
, __FILE__
, __LINE__
, 0,
345 "import name creds failed with: %d", maj_stat
);
346 gsm_error
= convert_gss_to_gsm(maj_stat
);
352 if (in_token
.length
) {
353 input_token
.length
= in_token
.length
;
354 input_token
.value
= in_token
.data
;
355 input_token_ptr
= &input_token
;
357 krb5_errx(context
, 1, "initcreds, context NULL, but not first req");
359 input_token
.length
= 0;
360 input_token
.value
= NULL
;
362 krb5_errx(context
, 1, "initcreds, context not NULL, but first req");
365 if ((flags
& GSS_C_DELEG_FLAG
) != 0)
366 logmessage(c
, __FILE__
, __LINE__
, 0, "init_sec_context delegating");
367 if ((flags
& GSS_C_DCE_STYLE
) != 0)
368 logmessage(c
, __FILE__
, __LINE__
, 0, "init_sec_context dce-style");
370 maj_stat
= gss_init_sec_context(&min_stat
,
383 if (GSS_ERROR(maj_stat
)) {
385 del_handle(&c
->handles
, hContext
);
387 logmessage(c
, __FILE__
, __LINE__
, 0,
388 "gss_init_sec_context returns code: %d/%d",
391 if (input_token
.length
== 0)
392 new_context_id
= add_handle(c
, handle_context
, ctx
);
394 new_context_id
= hContext
;
397 gsm_error
= convert_gss_to_gsm(maj_stat
);
399 if (output_token
.length
) {
400 out_token
.data
= output_token
.value
;
401 out_token
.length
= output_token
.length
;
405 logmessage(c
, __FILE__
, __LINE__
, 0,
406 "InitContext return code: %d", gsm_error
);
408 put32(c
, new_context_id
);
410 putdata(c
, out_token
);
412 gss_release_name(&min_stat
, &gss_target_name
);
413 if (output_token
.length
)
414 gss_release_buffer(&min_stat
, &output_token
);
415 krb5_data_free(&in_token
);
416 krb5_data_free(&target_name
);
422 HandleOP(AcceptContext
)
424 OM_uint32 maj_stat
, min_stat
, ret_flags
;
425 int32_t hContext
, deleg_hcred
, flags
;
427 int32_t new_context_id
= 0, gsm_error
= 0;
428 krb5_data out_token
= { 0 , NULL
};
431 gss_cred_id_t deleg_cred
= GSS_C_NO_CREDENTIAL
;
432 gss_buffer_desc input_token
, output_token
;
436 retdata(c
, in_token
);
438 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
442 if (in_token
.length
) {
443 input_token
.length
= in_token
.length
;
444 input_token
.value
= in_token
.data
;
446 input_token
.length
= 0;
447 input_token
.value
= NULL
;
450 maj_stat
= gss_accept_sec_context(&min_stat
,
454 GSS_C_NO_CHANNEL_BINDINGS
,
461 if (GSS_ERROR(maj_stat
)) {
463 del_handle(&c
->handles
, hContext
);
464 logmessage(c
, __FILE__
, __LINE__
, 0,
465 "gss_accept_sec_context returns code: %d/%d",
470 new_context_id
= add_handle(c
, handle_context
, ctx
);
472 new_context_id
= hContext
;
474 if (output_token
.length
) {
475 out_token
.data
= output_token
.value
;
476 out_token
.length
= output_token
.length
;
478 if ((ret_flags
& GSS_C_DCE_STYLE
) != 0)
479 logmessage(c
, __FILE__
, __LINE__
, 0, "accept_sec_context dce-style");
480 if ((ret_flags
& GSS_C_DELEG_FLAG
) != 0) {
481 deleg_hcred
= add_handle(c
, handle_cred
, deleg_cred
);
482 logmessage(c
, __FILE__
, __LINE__
, 0,
483 "accept_context delegated handle: %d", deleg_hcred
);
485 gss_release_cred(&min_stat
, &deleg_cred
);
490 gsm_error
= convert_gss_to_gsm(maj_stat
);
492 put32(c
, new_context_id
);
494 putdata(c
, out_token
);
495 put32(c
, deleg_hcred
);
497 if (output_token
.length
)
498 gss_release_buffer(&min_stat
, &output_token
);
499 krb5_data_free(&in_token
);
505 HandleOP(ToastResource
)
510 logmessage(c
, __FILE__
, __LINE__
, 0, "toasting %d", handle
);
511 del_handle(&c
->handles
, handle
);
518 HandleOP(AcquireCreds
)
520 char *name
, *password
;
521 int32_t gsm_error
, flags
, handle
= 0;
522 krb5_principal principal
= NULL
;
523 krb5_get_init_creds_opt
*opt
= NULL
;
527 retstring(c
, password
);
530 logmessage(c
, __FILE__
, __LINE__
, 0,
531 "username: %s password: %s", name
, password
);
533 ret
= krb5_parse_name(context
, name
, &principal
);
535 gsm_error
= convert_krb5_to_gsm(ret
);
539 ret
= krb5_get_init_creds_opt_alloc (context
, &opt
);
541 krb5_err(context
, 1, ret
, "krb5_get_init_creds_opt_alloc");
543 krb5_get_init_creds_opt_set_pa_password(context
, opt
, password
, NULL
);
545 gsm_error
= acquire_cred(c
, principal
, opt
, &handle
);
548 logmessage(c
, __FILE__
, __LINE__
, 0,
549 "AcquireCreds handle: %d return code: %d", handle
, gsm_error
);
552 krb5_get_init_creds_opt_free (context
, opt
);
554 krb5_free_principal(context
, principal
);
567 OM_uint32 maj_stat
, min_stat
;
568 int32_t hContext
, flags
, seqno
;
571 gss_buffer_desc input_token
, output_token
;
578 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
580 errx(1, "sign: reference to unknown context");
582 input_token
.length
= token
.length
;
583 input_token
.value
= token
.data
;
585 maj_stat
= gss_get_mic(&min_stat
, ctx
, 0, &input_token
,
587 if (maj_stat
!= GSS_S_COMPLETE
)
588 errx(1, "gss_get_mic failed");
590 krb5_data_free(&token
);
592 token
.data
= output_token
.value
;
593 token
.length
= output_token
.length
;
595 put32(c
, 0); /* XXX fix gsm_error */
598 gss_release_buffer(&min_stat
, &output_token
);
606 OM_uint32 maj_stat
, min_stat
;
607 int32_t hContext
, flags
, seqno
;
610 gss_buffer_desc msg_token
, mic_token
;
615 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
617 errx(1, "verify: reference to unknown context");
623 msg_token
.length
= msg
.length
;
624 msg_token
.value
= msg
.data
;
628 mic_token
.length
= mic
.length
;
629 mic_token
.value
= mic
.data
;
631 maj_stat
= gss_verify_mic(&min_stat
, ctx
, &msg_token
,
633 if (maj_stat
!= GSS_S_COMPLETE
)
634 errx(1, "gss_verify_mic failed");
636 krb5_data_free(&mic
);
637 krb5_data_free(&msg
);
639 put32(c
, 0); /* XXX fix gsm_error */
645 HandleOP(GetVersionAndCapabilities
)
647 int32_t cap
= HAS_MONIKER
;
648 char name
[256] = "unknown", *str
;
652 cap
|= ISSERVER
; /* is server */
657 if (uname(&ut
) == 0) {
658 snprintf(name
, sizeof(name
), "%s-%s-%s",
659 ut
.sysname
, ut
.version
, ut
.machine
);
664 ret
= asprintf(&str
, "gssmask %s %s", PACKAGE_STRING
, name
);
666 errx(1, "out of memory");
668 put32(c
, GSSMAGGOTPROTOCOL
);
677 HandleOP(GetTargetName
)
680 putstring(c
, targetname
);
687 HandleOP(SetLoggingSocket
)
695 logmessage(c
, __FILE__
, __LINE__
, 0,
696 "logging port on peer is: %d", (int)portnum
);
698 socket_set_port((struct sockaddr
*)(&c
->sa
), htons(portnum
));
700 sock
= socket(((struct sockaddr
*)&c
->sa
)->sa_family
, SOCK_STREAM
, 0);
701 if (sock
== rk_INVALID_SOCKET
)
704 ret
= connect(sock
, (struct sockaddr
*)&c
->sa
, c
->salen
);
706 logmessage(c
, __FILE__
, __LINE__
, 0, "failed connect to log port: %s",
708 rk_closesocket(sock
);
713 krb5_storage_free(c
->logging
);
714 c
->logging
= krb5_storage_from_socket(sock
);
715 rk_closesocket(sock
);
717 krb5_store_int32(c
->logging
, eLogSetMoniker
);
718 store_string(c
->logging
, c
->moniker
);
720 logmessage(c
, __FILE__
, __LINE__
, 0, "logging turned on");
727 HandleOP(ChangePassword
)
729 errx(1, "ChangePassword");
733 HandleOP(SetPasswordSelf
)
735 errx(1, "SetPasswordSelf");
741 OM_uint32 maj_stat
, min_stat
;
742 int32_t hContext
, flags
, seqno
;
745 gss_buffer_desc input_token
, output_token
;
753 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
755 errx(1, "wrap: reference to unknown context");
757 input_token
.length
= token
.length
;
758 input_token
.value
= token
.data
;
760 maj_stat
= gss_wrap(&min_stat
, ctx
, flags
, 0, &input_token
,
761 &conf_state
, &output_token
);
762 if (maj_stat
!= GSS_S_COMPLETE
)
763 errx(1, "gss_wrap failed");
765 krb5_data_free(&token
);
767 token
.data
= output_token
.value
;
768 token
.length
= output_token
.length
;
770 put32(c
, 0); /* XXX fix gsm_error */
773 gss_release_buffer(&min_stat
, &output_token
);
782 OM_uint32 maj_stat
, min_stat
;
783 int32_t hContext
, flags
, seqno
;
786 gss_buffer_desc input_token
, output_token
;
795 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
797 errx(1, "unwrap: reference to unknown context");
799 input_token
.length
= token
.length
;
800 input_token
.value
= token
.data
;
802 maj_stat
= gss_unwrap(&min_stat
, ctx
, &input_token
,
803 &output_token
, &conf_state
, &qop_state
);
805 if (maj_stat
!= GSS_S_COMPLETE
)
806 errx(1, "gss_unwrap failed: %d/%d", maj_stat
, min_stat
);
808 krb5_data_free(&token
);
809 if (maj_stat
== GSS_S_COMPLETE
) {
810 token
.data
= output_token
.value
;
811 token
.length
= output_token
.length
;
816 put32(c
, 0); /* XXX fix gsm_error */
819 if (maj_stat
== GSS_S_COMPLETE
)
820 gss_release_buffer(&min_stat
, &output_token
);
828 return handleWrap(op
, c
);
834 return handleUnwrap(op
, c
);
838 HandleOP(ConnectLoggingService2
)
840 errx(1, "ConnectLoggingService2");
846 putstring(c
, c
->moniker
);
851 HandleOP(CallExtension
)
853 errx(1, "CallExtension");
857 HandleOP(AcquirePKInitCreds
)
861 char fn
[] = "FILE:/tmp/pkcs12-creds-XXXXXXX";
862 krb5_principal principal
= NULL
;
868 fd
= mkstemp(fn
+ 5);
872 net_write(fd
, pfxdata
.data
, pfxdata
.length
);
873 krb5_data_free(&pfxdata
);
877 krb5_free_principal(context
, principal
);
879 put32(c
, -1); /* hResource */
880 put32(c
, GSMERR_NOT_SUPPORTED
);
887 OM_uint32 maj_stat
, min_stat
;
888 int32_t hContext
, flags
, bflags
;
889 krb5_data token
, header
, trailer
;
892 int conf_state
, iov_len
;
893 gss_iov_buffer_desc iov
[6];
902 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
904 errx(1, "wrap: reference to unknown context");
906 memset(&iov
, 0, sizeof(iov
));
908 iov_len
= sizeof(iov
)/sizeof(iov
[0]);
910 if (bflags
& WRAP_EXP_ONLY_HEADER
)
911 iov_len
-= 2; /* skip trailer and padding, aka dce-style */
913 iov
[0].type
= GSS_IOV_BUFFER_TYPE_HEADER
| GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE
;
914 if (header
.length
!= 0) {
915 iov
[1].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
916 iov
[1].buffer
.length
= header
.length
;
917 iov
[1].buffer
.value
= header
.data
;
919 iov
[1].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
921 iov
[2].type
= GSS_IOV_BUFFER_TYPE_DATA
;
922 iov
[2].buffer
.length
= token
.length
;
923 iov
[2].buffer
.value
= token
.data
;
924 if (trailer
.length
!= 0) {
925 iov
[3].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
926 iov
[3].buffer
.length
= trailer
.length
;
927 iov
[3].buffer
.value
= trailer
.data
;
929 iov
[3].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
931 iov
[4].type
= GSS_IOV_BUFFER_TYPE_PADDING
| GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE
;
932 iov
[5].type
= GSS_IOV_BUFFER_TYPE_TRAILER
| GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE
;
934 maj_stat
= gss_wrap_iov_length(&min_stat
, ctx
, flags
, 0, &conf_state
,
936 if (maj_stat
!= GSS_S_COMPLETE
)
937 errx(1, "gss_wrap_iov_length failed");
939 maj_stat
= gss_wrap_iov(&min_stat
, ctx
, flags
, 0, &conf_state
,
941 if (maj_stat
!= GSS_S_COMPLETE
)
942 errx(1, "gss_wrap_iov failed");
944 krb5_data_free(&token
);
946 token
.length
= iov
[0].buffer
.length
+ iov
[2].buffer
.length
+ iov
[4].buffer
.length
+ iov
[5].buffer
.length
;
947 token
.data
= malloc(token
.length
);
950 memcpy(p
, iov
[0].buffer
.value
, iov
[0].buffer
.length
);
951 p
+= iov
[0].buffer
.length
;
952 memcpy(p
, iov
[2].buffer
.value
, iov
[2].buffer
.length
);
953 p
+= iov
[2].buffer
.length
;
954 memcpy(p
, iov
[4].buffer
.value
, iov
[4].buffer
.length
);
955 p
+= iov
[4].buffer
.length
;
956 memcpy(p
, iov
[5].buffer
.value
, iov
[5].buffer
.length
);
957 p
+= iov
[5].buffer
.length
;
959 gss_release_iov_buffer(NULL
, iov
, iov_len
);
961 put32(c
, 0); /* XXX fix gsm_error */
973 OM_uint32 maj_stat
, min_stat
;
974 int32_t hContext
, flags
, bflags
;
975 krb5_data token
, header
, trailer
;
977 gss_iov_buffer_desc iov
[3];
978 int conf_state
, iov_len
;
988 iov_len
= sizeof(iov
)/sizeof(iov
[0]);
990 if (bflags
& WRAP_EXP_ONLY_HEADER
)
991 iov_len
-= 1; /* skip trailer and padding, aka dce-style */
993 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
995 errx(1, "unwrap: reference to unknown context");
997 if (header
.length
!= 0) {
998 iov
[0].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
999 iov
[0].buffer
.length
= header
.length
;
1000 iov
[0].buffer
.value
= header
.data
;
1002 iov
[0].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
1004 iov
[1].type
= GSS_IOV_BUFFER_TYPE_DATA
;
1005 iov
[1].buffer
.length
= token
.length
;
1006 iov
[1].buffer
.value
= token
.data
;
1008 if (trailer
.length
!= 0) {
1009 iov
[2].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
1010 iov
[2].buffer
.length
= trailer
.length
;
1011 iov
[2].buffer
.value
= trailer
.data
;
1013 iov
[2].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
1016 maj_stat
= gss_unwrap_iov(&min_stat
, ctx
, &conf_state
, &qop_state
,
1019 if (maj_stat
!= GSS_S_COMPLETE
)
1020 errx(1, "gss_unwrap failed: %d/%d", maj_stat
, min_stat
);
1022 if (maj_stat
== GSS_S_COMPLETE
) {
1023 token
.data
= iov
[1].buffer
.value
;
1024 token
.length
= iov
[1].buffer
.length
;
1029 put32(c
, 0); /* XXX fix gsm_error */
1040 enum gssMaggotOp op
;
1042 int (*func
)(enum gssMaggotOp
, struct client
*);
1045 #define S(a) { e##a, #a, handle##a }
1047 struct handler handlers
[] = {
1058 S(GetVersionAndCapabilities
),
1060 S(SetLoggingSocket
),
1065 S(ConnectLoggingService2
),
1068 S(AcquirePKInitCreds
),
1079 static struct handler
*
1084 for (i
= 0; i
< sizeof(handlers
)/sizeof(handlers
[0]); i
++)
1085 if (handlers
[i
].op
== op
)
1086 return &handlers
[i
];
1090 static struct client
*
1091 create_client(krb5_socket_t sock
, int port
, const char *moniker
)
1096 c
= ecalloc(1, sizeof(*c
));
1099 c
->moniker
= estrdup(moniker
);
1101 char hostname
[MAXHOSTNAMELEN
];
1102 gethostname(hostname
, sizeof(hostname
));
1103 ret
= asprintf(&c
->moniker
, "gssmask: %s:%d", hostname
, port
);
1109 errx(1, "out of memory");
1112 c
->salen
= sizeof(c
->sa
);
1113 getpeername(sock
, (struct sockaddr
*)&c
->sa
, &c
->salen
);
1115 getnameinfo((struct sockaddr
*)&c
->sa
, c
->salen
,
1116 c
->servername
, sizeof(c
->servername
),
1117 NULL
, 0, NI_NUMERICHOST
);
1120 c
->sock
= krb5_storage_from_socket(sock
);
1121 if (c
->sock
== NULL
)
1122 errx(1, "krb5_storage_from_socket");
1124 rk_closesocket(sock
);
1130 free_client(struct client
*c
)
1133 del_handle(&c
->handles
, c
->handles
->idx
);
1136 krb5_storage_free(c
->sock
);
1138 krb5_storage_free(c
->logging
);
1144 handleServer(void *ptr
)
1146 struct handler
*handler
;
1150 c
= (struct client
*)ptr
;
1156 handler
= find_op(op
);
1157 if (handler
== NULL
) {
1158 logmessage(c
, __FILE__
, __LINE__
, 0,
1159 "op %d not supported", (int)op
);
1163 logmessage(c
, __FILE__
, __LINE__
, 0,
1164 "---> Got op %s from server %s",
1165 handler
->name
, c
->servername
);
1167 if ((handler
->func
)(handler
->op
, c
))
1175 static char *port_str
;
1176 static int version_flag
;
1177 static int help_flag
;
1178 static char *logfile_str
;
1179 static char *moniker_str
;
1181 static int port
= 4711;
1183 struct getargs args
[] = {
1184 { "spn", 0, arg_string
, &targetname
, "This host's SPN",
1185 "service/host@REALM" },
1186 { "port", 'p', arg_string
, &port_str
, "Use this port",
1187 "number-of-service" },
1188 { "logfile", 0, arg_string
, &logfile_str
, "logfile",
1189 "number-of-service" },
1190 { "moniker", 0, arg_string
, &moniker_str
, "nickname",
1192 { "version", 0, arg_flag
, &version_flag
, "Print version",
1194 { "help", 0, arg_flag
, &help_flag
, NULL
,
1201 arg_printusage (args
,
1202 sizeof(args
) / sizeof(args
[0]),
1209 main(int argc
, char **argv
)
1213 setprogname (argv
[0]);
1215 if (getarg (args
, sizeof(args
) / sizeof(args
[0]), argc
, argv
, &optidx
))
1222 print_version (NULL
);
1232 port
= strtol (port_str
, &ptr
, 10);
1233 if (port
== 0 && ptr
== port_str
)
1234 errx (1, "Bad port `%s'", port_str
);
1237 krb5_init_context(&context
);
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
);