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
, ...)
78 vasprintf(&message
, fmt
, ap
);
82 fprintf(logfile
, "%s:%u: %d %s\n", file
, lineno
, level
, message
);
85 if (krb5_store_int32(c
->logging
, eLogInfo
) != 0)
86 errx(1, "krb5_store_int32: log level");
87 if (krb5_store_string(c
->logging
, file
) != 0)
88 errx(1, "krb5_store_string: filename");
89 if (krb5_store_int32(c
->logging
, lineno
) != 0)
90 errx(1, "krb5_store_string: filename");
91 if (krb5_store_string(c
->logging
, message
) != 0)
92 errx(1, "krb5_store_string: message");
93 if (krb5_ret_int32(c
->logging
, &ackid
) != 0)
94 errx(1, "krb5_ret_int32: ackid");
104 add_handle(struct client
*c
, enum handle_type type
, void *data
)
108 h
= ecalloc(1, sizeof(*h
));
110 h
->idx
= ++c
->nHandle
;
113 h
->next
= c
->handles
;
120 del_handle(struct handle
**h
, int32_t idx
)
128 if ((*h
)->idx
== idx
) {
129 struct handle
*p
= *h
;
132 case handle_context
: {
133 gss_ctx_id_t c
= p
->ptr
;
134 gss_delete_sec_context(&min_stat
, &c
, NULL
);
137 gss_cred_id_t c
= p
->ptr
;
138 gss_release_cred(&min_stat
, &c
);
146 errx(1, "tried to delete an unexisting handle");
150 find_handle(struct handle
*h
, int32_t idx
, enum handle_type type
)
159 errx(1, "monger switched type on handle!");
168 convert_gss_to_gsm(OM_uint32 maj_stat
)
173 case GSS_S_CONTINUE_NEEDED
:
174 return GSMERR_CONTINUE_NEEDED
;
175 case GSS_S_DEFECTIVE_TOKEN
:
176 return GSMERR_INVALID_TOKEN
;
178 return GSMERR_AP_MODIFIED
;
185 convert_krb5_to_gsm(krb5_error_code ret
)
200 acquire_cred(struct client
*c
,
201 krb5_principal principal
,
202 krb5_get_init_creds_opt
*opt
,
209 OM_uint32 maj_stat
, min_stat
;
213 krb5_get_init_creds_opt_set_forwardable (opt
, 1);
214 krb5_get_init_creds_opt_set_renew_life (opt
, 3600 * 24 * 30);
216 memset(&cred
, 0, sizeof(cred
));
218 ret
= krb5_get_init_creds_password (context
,
228 logmessage(c
, __FILE__
, __LINE__
, 0,
229 "krb5_get_init_creds failed: %d", ret
);
230 return convert_krb5_to_gsm(ret
);
233 ret
= krb5_cc_new_unique(context
, "MEMORY", NULL
, &id
);
235 krb5_err (context
, 1, ret
, "krb5_cc_initialize");
237 ret
= krb5_cc_initialize (context
, id
, cred
.client
);
239 krb5_err (context
, 1, ret
, "krb5_cc_initialize");
241 ret
= krb5_cc_store_cred (context
, id
, &cred
);
243 krb5_err (context
, 1, ret
, "krb5_cc_store_cred");
245 krb5_free_cred_contents (context
, &cred
);
247 maj_stat
= gss_krb5_import_cred(&min_stat
,
252 krb5_cc_close(context
, id
);
254 logmessage(c
, __FILE__
, __LINE__
, 0,
255 "krb5 import creds failed with: %d", maj_stat
);
256 return convert_gss_to_gsm(maj_stat
);
259 *handle
= add_handle(c
, handle_cred
, gcred
);
269 #define HandleOP(h) \
270 handle##h(enum gssMaggotOp op, struct client *c)
277 HandleOP(GetVersionInfo
)
279 put32(c
, GSSMAGGOTPROTOCOL
);
280 errx(1, "GetVersionInfo");
286 struct handle
*h
= c
->handles
;
295 logmessage(c
, __FILE__
, __LINE__
, 0,
296 "Did not toast all resources: %d", i
);
301 HandleOP(InitContext
)
303 OM_uint32 maj_stat
, min_stat
, ret_flags
;
304 int32_t hContext
, hCred
, flags
;
305 krb5_data target_name
, in_token
;
306 int32_t new_context_id
= 0, gsm_error
= 0;
307 krb5_data out_token
= { 0 , NULL
};
311 gss_name_t gss_target_name
;
312 gss_buffer_desc input_token
, output_token
;
313 gss_OID oid
= GSS_C_NO_OID
;
314 gss_buffer_t input_token_ptr
= GSS_C_NO_BUFFER
;
319 retdata(c
, target_name
);
320 retdata(c
, in_token
);
322 logmessage(c
, __FILE__
, __LINE__
, 0,
323 "targetname: <%.*s>", (int)target_name
.length
,
324 (char *)target_name
.data
);
326 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
329 creds
= find_handle(c
->handles
, hCred
, handle_cred
);
333 input_token
.length
= target_name
.length
;
334 input_token
.value
= target_name
.data
;
336 maj_stat
= gss_import_name(&min_stat
,
338 GSS_KRB5_NT_PRINCIPAL_NAME
,
340 if (GSS_ERROR(maj_stat
)) {
341 logmessage(c
, __FILE__
, __LINE__
, 0,
342 "import name creds failed with: %d", maj_stat
);
343 gsm_error
= convert_gss_to_gsm(maj_stat
);
349 if (in_token
.length
) {
350 input_token
.length
= in_token
.length
;
351 input_token
.value
= in_token
.data
;
352 input_token_ptr
= &input_token
;
354 krb5_errx(context
, 1, "initcreds, context NULL, but not first req");
356 input_token
.length
= 0;
357 input_token
.value
= NULL
;
359 krb5_errx(context
, 1, "initcreds, context not NULL, but first req");
362 if ((flags
& GSS_C_DELEG_FLAG
) != 0)
363 logmessage(c
, __FILE__
, __LINE__
, 0, "init_sec_context delegating");
364 if ((flags
& GSS_C_DCE_STYLE
) != 0)
365 logmessage(c
, __FILE__
, __LINE__
, 0, "init_sec_context dce-style");
367 maj_stat
= gss_init_sec_context(&min_stat
,
380 if (GSS_ERROR(maj_stat
)) {
382 del_handle(&c
->handles
, hContext
);
384 logmessage(c
, __FILE__
, __LINE__
, 0,
385 "gss_init_sec_context returns code: %d/%d",
388 if (input_token
.length
== 0)
389 new_context_id
= add_handle(c
, handle_context
, ctx
);
391 new_context_id
= hContext
;
394 gsm_error
= convert_gss_to_gsm(maj_stat
);
396 if (output_token
.length
) {
397 out_token
.data
= output_token
.value
;
398 out_token
.length
= output_token
.length
;
402 logmessage(c
, __FILE__
, __LINE__
, 0,
403 "InitContext return code: %d", gsm_error
);
405 put32(c
, new_context_id
);
407 putdata(c
, out_token
);
409 gss_release_name(&min_stat
, &gss_target_name
);
410 if (output_token
.length
)
411 gss_release_buffer(&min_stat
, &output_token
);
412 krb5_data_free(&in_token
);
413 krb5_data_free(&target_name
);
419 HandleOP(AcceptContext
)
421 OM_uint32 maj_stat
, min_stat
, ret_flags
;
422 int32_t hContext
, deleg_hcred
, flags
;
424 int32_t new_context_id
= 0, gsm_error
= 0;
425 krb5_data out_token
= { 0 , NULL
};
428 gss_cred_id_t deleg_cred
= GSS_C_NO_CREDENTIAL
;
429 gss_buffer_desc input_token
, output_token
;
430 gss_buffer_t input_token_ptr
= GSS_C_NO_BUFFER
;
434 retdata(c
, in_token
);
436 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
440 if (in_token
.length
) {
441 input_token
.length
= in_token
.length
;
442 input_token
.value
= in_token
.data
;
443 input_token_ptr
= &input_token
;
445 input_token
.length
= 0;
446 input_token
.value
= NULL
;
449 maj_stat
= gss_accept_sec_context(&min_stat
,
453 GSS_C_NO_CHANNEL_BINDINGS
,
460 if (GSS_ERROR(maj_stat
)) {
462 del_handle(&c
->handles
, hContext
);
463 logmessage(c
, __FILE__
, __LINE__
, 0,
464 "gss_accept_sec_context returns code: %d/%d",
469 new_context_id
= add_handle(c
, handle_context
, ctx
);
471 new_context_id
= hContext
;
473 if (output_token
.length
) {
474 out_token
.data
= output_token
.value
;
475 out_token
.length
= output_token
.length
;
477 if ((ret_flags
& GSS_C_DCE_STYLE
) != 0)
478 logmessage(c
, __FILE__
, __LINE__
, 0, "accept_sec_context dce-style");
479 if ((ret_flags
& GSS_C_DELEG_FLAG
) != 0) {
480 deleg_hcred
= add_handle(c
, handle_cred
, deleg_cred
);
481 logmessage(c
, __FILE__
, __LINE__
, 0,
482 "accept_context delegated handle: %d", deleg_hcred
);
484 gss_release_cred(&min_stat
, &deleg_cred
);
489 gsm_error
= convert_gss_to_gsm(maj_stat
);
491 put32(c
, new_context_id
);
493 putdata(c
, out_token
);
494 put32(c
, deleg_hcred
);
496 if (output_token
.length
)
497 gss_release_buffer(&min_stat
, &output_token
);
498 krb5_data_free(&in_token
);
504 HandleOP(ToastResource
)
509 logmessage(c
, __FILE__
, __LINE__
, 0, "toasting %d", handle
);
510 del_handle(&c
->handles
, handle
);
517 HandleOP(AcquireCreds
)
519 char *name
, *password
;
520 int32_t gsm_error
, flags
, handle
= 0;
521 krb5_principal principal
= NULL
;
522 krb5_get_init_creds_opt
*opt
= NULL
;
526 retstring(c
, password
);
529 logmessage(c
, __FILE__
, __LINE__
, 0,
530 "username: %s password: %s", name
, password
);
532 ret
= krb5_parse_name(context
, name
, &principal
);
534 gsm_error
= convert_krb5_to_gsm(ret
);
538 ret
= krb5_get_init_creds_opt_alloc (context
, &opt
);
540 krb5_err(context
, 1, ret
, "krb5_get_init_creds_opt_alloc");
542 krb5_get_init_creds_opt_set_pa_password(context
, opt
, password
, NULL
);
544 gsm_error
= acquire_cred(c
, principal
, opt
, &handle
);
547 logmessage(c
, __FILE__
, __LINE__
, 0,
548 "AcquireCreds handle: %d return code: %d", handle
, gsm_error
);
551 krb5_get_init_creds_opt_free (context
, opt
);
553 krb5_free_principal(context
, principal
);
566 OM_uint32 maj_stat
, min_stat
;
567 int32_t hContext
, flags
, seqno
;
570 gss_buffer_desc input_token
, output_token
;
577 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
579 errx(1, "sign: reference to unknown context");
581 input_token
.length
= token
.length
;
582 input_token
.value
= token
.data
;
584 maj_stat
= gss_get_mic(&min_stat
, ctx
, 0, &input_token
,
586 if (maj_stat
!= GSS_S_COMPLETE
)
587 errx(1, "gss_get_mic failed");
589 krb5_data_free(&token
);
591 token
.data
= output_token
.value
;
592 token
.length
= output_token
.length
;
594 put32(c
, 0); /* XXX fix gsm_error */
597 gss_release_buffer(&min_stat
, &output_token
);
605 OM_uint32 maj_stat
, min_stat
;
606 int32_t hContext
, flags
, seqno
;
609 gss_buffer_desc msg_token
, mic_token
;
614 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
616 errx(1, "verify: reference to unknown context");
622 msg_token
.length
= msg
.length
;
623 msg_token
.value
= msg
.data
;
627 mic_token
.length
= mic
.length
;
628 mic_token
.value
= mic
.data
;
630 maj_stat
= gss_verify_mic(&min_stat
, ctx
, &msg_token
,
632 if (maj_stat
!= GSS_S_COMPLETE
)
633 errx(1, "gss_verify_mic failed");
635 krb5_data_free(&mic
);
636 krb5_data_free(&msg
);
638 put32(c
, 0); /* XXX fix gsm_error */
644 HandleOP(GetVersionAndCapabilities
)
646 int32_t cap
= HAS_MONIKER
;
647 char name
[256] = "unknown", *str
;
650 cap
|= ISSERVER
; /* is server */
655 if (uname(&ut
) == 0) {
656 snprintf(name
, sizeof(name
), "%s-%s-%s",
657 ut
.sysname
, ut
.version
, ut
.machine
);
662 asprintf(&str
, "gssmask %s %s", PACKAGE_STRING
, name
);
664 put32(c
, GSSMAGGOTPROTOCOL
);
673 HandleOP(GetTargetName
)
676 putstring(c
, targetname
);
683 HandleOP(SetLoggingSocket
)
690 logmessage(c
, __FILE__
, __LINE__
, 0,
691 "logging port on peer is: %d", (int)portnum
);
693 socket_set_port((struct sockaddr
*)(&c
->sa
), htons(portnum
));
695 fd
= socket(((struct sockaddr
*)&c
->sa
)->sa_family
, SOCK_STREAM
, 0);
699 ret
= connect(fd
, (struct sockaddr
*)&c
->sa
, c
->salen
);
701 logmessage(c
, __FILE__
, __LINE__
, 0, "failed connect to log port: %s",
708 krb5_storage_free(c
->logging
);
709 c
->logging
= krb5_storage_from_fd(fd
);
712 krb5_store_int32(c
->logging
, eLogSetMoniker
);
713 store_string(c
->logging
, c
->moniker
);
715 logmessage(c
, __FILE__
, __LINE__
, 0, "logging turned on");
722 HandleOP(ChangePassword
)
724 errx(1, "ChangePassword");
728 HandleOP(SetPasswordSelf
)
730 errx(1, "SetPasswordSelf");
736 OM_uint32 maj_stat
, min_stat
;
737 int32_t hContext
, flags
, seqno
;
740 gss_buffer_desc input_token
, output_token
;
748 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
750 errx(1, "wrap: reference to unknown context");
752 input_token
.length
= token
.length
;
753 input_token
.value
= token
.data
;
755 maj_stat
= gss_wrap(&min_stat
, ctx
, flags
, 0, &input_token
,
756 &conf_state
, &output_token
);
757 if (maj_stat
!= GSS_S_COMPLETE
)
758 errx(1, "gss_wrap failed");
760 krb5_data_free(&token
);
762 token
.data
= output_token
.value
;
763 token
.length
= output_token
.length
;
765 put32(c
, 0); /* XXX fix gsm_error */
768 gss_release_buffer(&min_stat
, &output_token
);
777 OM_uint32 maj_stat
, min_stat
;
778 int32_t hContext
, flags
, seqno
;
781 gss_buffer_desc input_token
, output_token
;
790 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
792 errx(1, "unwrap: reference to unknown context");
794 input_token
.length
= token
.length
;
795 input_token
.value
= token
.data
;
797 maj_stat
= gss_unwrap(&min_stat
, ctx
, &input_token
,
798 &output_token
, &conf_state
, &qop_state
);
800 if (maj_stat
!= GSS_S_COMPLETE
)
801 errx(1, "gss_unwrap failed: %d/%d", maj_stat
, min_stat
);
803 krb5_data_free(&token
);
804 if (maj_stat
== GSS_S_COMPLETE
) {
805 token
.data
= output_token
.value
;
806 token
.length
= output_token
.length
;
811 put32(c
, 0); /* XXX fix gsm_error */
814 if (maj_stat
== GSS_S_COMPLETE
)
815 gss_release_buffer(&min_stat
, &output_token
);
823 return handleWrap(op
, c
);
829 return handleUnwrap(op
, c
);
833 HandleOP(ConnectLoggingService2
)
835 errx(1, "ConnectLoggingService2");
841 putstring(c
, c
->moniker
);
846 HandleOP(CallExtension
)
848 errx(1, "CallExtension");
851 krb5_error_code KRB5_LIB_FUNCTION
852 _krb5_pk_enterprise_cert (
853 krb5_context
/*context*/,
854 const char */
*user_id*/
,
855 krb5_const_realm
/*realm*/,
856 krb5_principal */
*principal*/
);
860 HandleOP(AcquirePKInitCreds
)
865 char fn
[] = "FILE:/tmp/pkcs12-creds-XXXXXXX";
866 const char *default_realm
= "H5L.ORG";
867 krb5_principal principal
= NULL
;
873 fd
= mkstemp(fn
+ 5);
877 net_write(fd
, pfxdata
.data
, pfxdata
.length
);
878 krb5_data_free(&pfxdata
);
881 /* get credentials */
883 ret
= _krb5_pk_enterprise_cert(context
, fn
, default_realm
, &principal
);
885 krb5_err(context
, 1, ret
, "krb5_pk_enterprise_certs");
889 krb5_free_principal(context
, principal
);
891 put32(c
, -1); /* hResource */
892 put32(c
, GSMERR_NOT_SUPPORTED
);
899 OM_uint32 maj_stat
, min_stat
;
900 int32_t hContext
, flags
, bflags
;
901 krb5_data token
, header
, trailer
;
904 int conf_state
, iov_len
;
905 gss_iov_buffer_desc iov
[6];
914 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
916 errx(1, "wrap: reference to unknown context");
918 memset(&iov
, 0, sizeof(iov
));
920 iov_len
= sizeof(iov
)/sizeof(iov
[0]);
922 if (bflags
& WRAP_EXP_ONLY_HEADER
)
923 iov_len
-= 2; /* skip trailer and padding, aka dce-style */
925 iov
[0].type
= GSS_IOV_BUFFER_TYPE_HEADER
| GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE
;
926 if (header
.length
!= 0) {
927 iov
[1].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
928 iov
[1].buffer
.length
= header
.length
;
929 iov
[1].buffer
.value
= header
.data
;
931 iov
[1].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
933 iov
[2].type
= GSS_IOV_BUFFER_TYPE_DATA
;
934 iov
[2].buffer
.length
= token
.length
;
935 iov
[2].buffer
.value
= token
.data
;
936 if (trailer
.length
!= 0) {
937 iov
[3].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
938 iov
[3].buffer
.length
= trailer
.length
;
939 iov
[3].buffer
.value
= trailer
.data
;
941 iov
[3].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
943 iov
[4].type
= GSS_IOV_BUFFER_TYPE_PADDING
| GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE
;
944 iov
[5].type
= GSS_IOV_BUFFER_TYPE_TRAILER
| GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE
;
946 maj_stat
= gss_wrap_iov_length(&min_stat
, ctx
, flags
, 0, &conf_state
,
948 if (maj_stat
!= GSS_S_COMPLETE
)
949 errx(1, "gss_wrap_iov_length failed");
951 maj_stat
= gss_wrap_iov(&min_stat
, ctx
, flags
, 0, &conf_state
,
953 if (maj_stat
!= GSS_S_COMPLETE
)
954 errx(1, "gss_wrap_iov failed");
956 krb5_data_free(&token
);
958 token
.length
= iov
[0].buffer
.length
+ iov
[2].buffer
.length
+ iov
[4].buffer
.length
+ iov
[5].buffer
.length
;
959 token
.data
= malloc(token
.length
);
962 memcpy(p
, iov
[0].buffer
.value
, iov
[0].buffer
.length
);
963 p
+= iov
[0].buffer
.length
;
964 memcpy(p
, iov
[2].buffer
.value
, iov
[2].buffer
.length
);
965 p
+= iov
[2].buffer
.length
;
966 memcpy(p
, iov
[4].buffer
.value
, iov
[4].buffer
.length
);
967 p
+= iov
[4].buffer
.length
;
968 memcpy(p
, iov
[5].buffer
.value
, iov
[5].buffer
.length
);
969 p
+= iov
[5].buffer
.length
;
971 gss_release_iov_buffer(NULL
, iov
, iov_len
);
973 put32(c
, 0); /* XXX fix gsm_error */
985 OM_uint32 maj_stat
, min_stat
;
986 int32_t hContext
, flags
, bflags
;
987 krb5_data token
, header
, trailer
;
989 gss_iov_buffer_desc iov
[3];
990 int conf_state
, iov_len
;
1000 iov_len
= sizeof(iov
)/sizeof(iov
[0]);
1002 if (bflags
& WRAP_EXP_ONLY_HEADER
)
1003 iov_len
-= 1; /* skip trailer and padding, aka dce-style */
1005 ctx
= find_handle(c
->handles
, hContext
, handle_context
);
1007 errx(1, "unwrap: reference to unknown context");
1009 if (header
.length
!= 0) {
1010 iov
[0].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
1011 iov
[0].buffer
.length
= header
.length
;
1012 iov
[0].buffer
.value
= header
.data
;
1014 iov
[0].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
1016 iov
[1].type
= GSS_IOV_BUFFER_TYPE_DATA
;
1017 iov
[1].buffer
.length
= token
.length
;
1018 iov
[1].buffer
.value
= token
.data
;
1020 if (trailer
.length
!= 0) {
1021 iov
[2].type
= GSS_IOV_BUFFER_TYPE_SIGN_ONLY
;
1022 iov
[2].buffer
.length
= trailer
.length
;
1023 iov
[2].buffer
.value
= trailer
.data
;
1025 iov
[2].type
= GSS_IOV_BUFFER_TYPE_EMPTY
;
1028 maj_stat
= gss_unwrap_iov(&min_stat
, ctx
, &conf_state
, &qop_state
,
1031 if (maj_stat
!= GSS_S_COMPLETE
)
1032 errx(1, "gss_unwrap failed: %d/%d", maj_stat
, min_stat
);
1034 if (maj_stat
== GSS_S_COMPLETE
) {
1035 token
.data
= iov
[1].buffer
.value
;
1036 token
.length
= iov
[1].buffer
.length
;
1041 put32(c
, 0); /* XXX fix gsm_error */
1052 enum gssMaggotOp op
;
1054 int (*func
)(enum gssMaggotOp
, struct client
*);
1057 #define S(a) { e##a, #a, handle##a }
1059 struct handler handlers
[] = {
1070 S(GetVersionAndCapabilities
),
1072 S(SetLoggingSocket
),
1077 S(ConnectLoggingService2
),
1080 S(AcquirePKInitCreds
),
1091 static struct handler
*
1096 for (i
= 0; i
< sizeof(handlers
)/sizeof(handlers
[0]); i
++)
1097 if (handlers
[i
].op
== op
)
1098 return &handlers
[i
];
1102 static struct client
*
1103 create_client(int fd
, int port
, const char *moniker
)
1107 c
= ecalloc(1, sizeof(*c
));
1110 c
->moniker
= estrdup(moniker
);
1112 char hostname
[MAXHOSTNAMELEN
];
1113 gethostname(hostname
, sizeof(hostname
));
1114 asprintf(&c
->moniker
, "gssmask: %s:%d", hostname
, port
);
1118 c
->salen
= sizeof(c
->sa
);
1119 getpeername(fd
, (struct sockaddr
*)&c
->sa
, &c
->salen
);
1121 getnameinfo((struct sockaddr
*)&c
->sa
, c
->salen
,
1122 c
->servername
, sizeof(c
->servername
),
1123 NULL
, 0, NI_NUMERICHOST
);
1126 c
->sock
= krb5_storage_from_fd(fd
);
1127 if (c
->sock
== NULL
)
1128 errx(1, "krb5_storage_from_fd");
1136 free_client(struct client
*c
)
1139 del_handle(&c
->handles
, c
->handles
->idx
);
1142 krb5_storage_free(c
->sock
);
1144 krb5_storage_free(c
->logging
);
1150 handleServer(void *ptr
)
1152 struct handler
*handler
;
1156 c
= (struct client
*)ptr
;
1162 handler
= find_op(op
);
1163 if (handler
== NULL
) {
1164 logmessage(c
, __FILE__
, __LINE__
, 0,
1165 "op %d not supported", (int)op
);
1169 logmessage(c
, __FILE__
, __LINE__
, 0,
1170 "---> Got op %s from server %s",
1171 handler
->name
, c
->servername
);
1173 if ((handler
->func
)(handler
->op
, c
))
1181 static char *port_str
;
1182 static int version_flag
;
1183 static int help_flag
;
1184 static char *logfile_str
;
1185 static char *moniker_str
;
1187 static int port
= 4711;
1189 struct getargs args
[] = {
1190 { "spn", 0, arg_string
, &targetname
, "This host's SPN",
1191 "service/host@REALM" },
1192 { "port", 'p', arg_string
, &port_str
, "Use this port",
1193 "number-of-service" },
1194 { "logfile", 0, arg_string
, &logfile_str
, "logfile",
1195 "number-of-service" },
1196 { "moniker", 0, arg_string
, &moniker_str
, "nickname",
1198 { "version", 0, arg_flag
, &version_flag
, "Print version",
1200 { "help", 0, arg_flag
, &help_flag
, NULL
,
1207 arg_printusage (args
,
1208 sizeof(args
) / sizeof(args
[0]),
1215 main(int argc
, char **argv
)
1219 setprogname (argv
[0]);
1221 if (getarg (args
, sizeof(args
) / sizeof(args
[0]), argc
, argv
, &optidx
))
1228 print_version (NULL
);
1238 port
= strtol (port_str
, &ptr
, 10);
1239 if (port
== 0 && ptr
== port_str
)
1240 errx (1, "Bad port `%s'", port_str
);
1243 krb5_init_context(&context
);
1246 const char *lf
= logfile_str
;
1250 logfile
= fopen(lf
, "w");
1251 if (logfile
== NULL
)
1252 err(1, "error opening %s", lf
);
1255 mini_inetd(htons(port
));
1256 fprintf(logfile
, "connected\n");
1261 c
= create_client(0, port
, moniker_str
);
1269 krb5_free_context(context
);