}
+static void
+copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
+ krb5_error_code code;
+ krb5_ticket *ticket;
+ size_t len;
+
+ code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
+ if (code == 0) {
+ len = krb5_princ_realm(context, ticket->server)->length;
+ if (len > destlen - 1)
+ len = destlen - 1;
+
+ strncpy(dest, len, krb5_princ_realm(context, ticket->server)->data);
+ dest[len] = '\0';
+
+ pkrb5_free_ticket(context, ticket);
+ }
+}
+
int
KFW_AFS_klog(
krb5_context alt_ctx,
else
strcpy(CellName, cell);
+ /* This is for Kerberos v4 only */
if (strlen(realm) == 0)
strcpy(RealmName, realm_of_cell);
else
if ( try_krb5 ) {
int len;
+ code = KRB5KRB_ERR_GENERIC;
- /* First try service/cell@REALM */
- if (code = pkrb5_build_principal(ctx, &increds.server,
- (int)strlen(RealmName),
- RealmName,
- ServiceName,
- CellName,
- 0))
- {
- goto cleanup;
- }
increds.client = client_principal;
increds.times.endtime = 0;
/* Ask for DES since that is what V4 understands */
increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
-
- if ( IsDebuggerPresent() ) {
- char * cname, *sname;
- pkrb5_unparse_name(ctx, increds.client, &cname);
- pkrb5_unparse_name(ctx, increds.server, &sname);
- OutputDebugString("Getting tickets for \"");
- OutputDebugString(cname);
- OutputDebugString("\" and service \"");
- OutputDebugString(sname);
- OutputDebugString("\"\n");
- pkrb5_free_unparsed_name(ctx,cname);
- pkrb5_free_unparsed_name(ctx,sname);
- }
-
- code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
- if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
- code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
- code == KRB5KRB_AP_ERR_MSG_TYPE) {
- /* Or service@REALM */
- pkrb5_free_principal(ctx,increds.server);
+ /* If there was a specific realm we are supposed to try
+ * then use it
+ */
+ if (strlen(realm) != 0) {
+ /* service/cell@REALM */
increds.server = 0;
code = pkrb5_build_principal(ctx, &increds.server,
- (int)strlen(RealmName),
- RealmName,
- ServiceName,
- 0);
-
+ (int)strlen(realm),
+ realm,
+ ServiceName,
+ CellName,
+ 0);
if ( IsDebuggerPresent() ) {
char * cname, *sname;
pkrb5_unparse_name(ctx, increds.client, &cname);
pkrb5_unparse_name(ctx, increds.server, &sname);
- OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
- OutputDebugString("Trying again: getting tickets for \"");
+ OutputDebugString("Getting tickets for \"");
OutputDebugString(cname);
OutputDebugString("\" and service \"");
OutputDebugString(sname);
if (!code)
code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
- }
- if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
- code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
- code == KRB5KRB_AP_ERR_MSG_TYPE) &&
- strcmp(RealmName, realm_of_cell)) {
- /* Or service/cell@REALM_OF_CELL */
- strcpy(RealmName, realm_of_cell);
- pkrb5_free_principal(ctx,increds.server);
- increds.server = 0;
- code = pkrb5_build_principal(ctx, &increds.server,
- (int)strlen(RealmName),
- RealmName,
- ServiceName,
- CellName,
- 0);
+ if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ code == KRB5_ERR_HOST_REALM_UNKNOWN ||
+ code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
+ code == KRB5KRB_AP_ERR_MSG_TYPE) {
+ /* Or service@REALM */
+ pkrb5_free_principal(ctx,increds.server);
+ increds.server = 0;
+ code = pkrb5_build_principal(ctx, &increds.server,
+ (int)strlen(realm),
+ realm,
+ ServiceName,
+ 0);
+
+ if ( IsDebuggerPresent() ) {
+ char * cname, *sname;
+ pkrb5_unparse_name(ctx, increds.client, &cname);
+ pkrb5_unparse_name(ctx, increds.server, &sname);
+ OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
+ OutputDebugString("Trying again: getting tickets for \"");
+ OutputDebugString(cname);
+ OutputDebugString("\" and service \"");
+ OutputDebugString(sname);
+ OutputDebugString("\"\n");
+ pkrb5_free_unparsed_name(ctx,cname);
+ pkrb5_free_unparsed_name(ctx,sname);
+ }
+
+ if (!code)
+ code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+ }
+
+ if (code == 0) {
+ /* we have a local realm for the cell */
+ strcpy(realm_of_cell, realm);
+ }
+ } else {
+ /* Otherwise, first try service/cell@CLIENT_REALM */
+ if (code = pkrb5_build_principal(ctx, &increds.server,
+ (int)strlen(realm_of_user),
+ realm_of_user,
+ ServiceName,
+ CellName,
+ 0))
+ {
+ goto cleanup;
+ }
if ( IsDebuggerPresent() ) {
char * cname, *sname;
pkrb5_unparse_name(ctx, increds.client, &cname);
pkrb5_unparse_name(ctx, increds.server, &sname);
- OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
- OutputDebugString("Trying again: getting tickets for \"");
+ OutputDebugString("Getting tickets for \"");
OutputDebugString(cname);
OutputDebugString("\" and service \"");
OutputDebugString(sname);
pkrb5_free_unparsed_name(ctx,sname);
}
- if (!code)
- code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+ code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+ if (code == 0) {
+ /* The client's realm is a local realm for the cell.
+ * Save it so that later the pts registration will not
+ * be performed.
+ */
+ strcpy(realm_of_cell, realm_of_user);
+ }
-
- if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ code == KRB5_ERR_HOST_REALM_UNKNOWN ||
code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
- code == KRB5KRB_AP_ERR_MSG_TYPE) {
- /* Or service@REALM_OF_CELL */
+ code == KRB5KRB_AP_ERR_MSG_TYPE) &&
+ strcmp(realm_of_user, realm_of_cell)) {
+ /* Then service/cell@CELL_REALM */
+ pkrb5_free_principal(ctx,increds.server);
+ increds.server = 0;
+ code = pkrb5_build_principal(ctx, &increds.server,
+ (int)strlen(realm_of_cell),
+ realm_of_cell,
+ ServiceName,
+ CellName,
+ 0);
+ if ( IsDebuggerPresent() ) {
+ char * cname, *sname;
+ pkrb5_unparse_name(ctx, increds.client, &cname);
+ pkrb5_unparse_name(ctx, increds.server, &sname);
+ OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
+ OutputDebugString("Trying again: getting tickets for \"");
+ OutputDebugString(cname);
+ OutputDebugString("\" and service \"");
+ OutputDebugString(sname);
+ OutputDebugString("\"\n");
+ pkrb5_free_unparsed_name(ctx,cname);
+ pkrb5_free_unparsed_name(ctx,sname);
+ }
+
+ if (!code)
+ code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+
+ if (!code && !strlen(realm_of_cell))
+ copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
+ }
+
+ if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ code == KRB5_ERR_HOST_REALM_UNKNOWN ||
+ code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
+ code == KRB5KRB_AP_ERR_MSG_TYPE) {
+ /* Finally service@CELL_REALM */
pkrb5_free_principal(ctx,increds.server);
increds.server = 0;
code = pkrb5_build_principal(ctx, &increds.server,
- (int)strlen(RealmName),
- RealmName,
+ (int)strlen(realm_of_cell),
+ realm_of_cell,
ServiceName,
0);
if (!code)
code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+ if (!code && !strlen(realm_of_cell))
+ copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
}
}
*/
/*
- * Copyright (c) 2007 Secure Endpoints Inc.
+ * Copyright (c) 2007-2008 Secure Endpoints Inc.
*
* All rights reserved.
*
return(KSUCCESS);
}
+static void
+copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
+ krb5_error_code code;
+ krb5_ticket *ticket;
+ size_t len;
+
+ code = krb5_decode_ticket(&v5cred->ticket, &ticket);
+ if (code == 0) {
+ len = krb5_princ_realm(context, ticket->server)->length;
+ if (len > destlen - 1)
+ len = destlen - 1;
+
+ strncpy(dest, len, krb5_princ_realm(context, ticket->server)->data);
+ dest[len] = '\0';
+
+ krb5_free_ticket(context, ticket);
+ }
+}
+
/*
* Log to a cell. If the cell has already been logged to, return without
* doing anything. Otherwise, log to it and mark that it has been logged
int retry = 1;
int realm_fallback = 0;
+ if ((status = get_v5_user_realm(context, realm_of_user)) != KSUCCESS) {
+ fprintf(stderr, "%s: Couldn't determine realm of user: %d\n",
+ progname, status);
+ return(AKLOG_KERBEROS);
+ }
+
if ( strchr(name,'.') != NULL ) {
fprintf(stderr, "%s: Can't support principal names including a dot.\n",
progname);
}
try_v5:
- if (realm && realm[0])
- strcpy(realm_of_cell, realm);
- else
- strcpy(realm_of_cell,
- afs_realm_of_cell5(context, &ak_cellconfig, realm_fallback));
-
- if (dflag)
- printf("Getting v5 tickets: %s/%s@%s\n", name, instance, realm_of_cell);
- status = get_v5cred(context, name, instance, realm_of_cell,
+ if (realm && realm[0]) {
+ if (dflag)
+ printf("Getting v5 tickets: %s/%s@%s\n", name, instance, realm);
+ status = get_v5cred(context, name, instance, realm,
#ifdef HAVE_KRB4
use524 ? &c : NULL,
#else
NULL,
#endif
&v5cred);
+ strcpy(realm_of_cell, realm);
+ } else {
+ strcpy(realm_of_cell,
+ afs_realm_of_cell5(context, &ak_cellconfig, realm_fallback));
- if (status == 0 && strcmp(realm_of_cell, "") == 0) {
- krb5_error_code code;
- krb5_ticket *ticket;
-
- code = krb5_decode_ticket(&v5cred->ticket, &ticket);
-
- if (code != 0) {
- fprintf(stderr,
- "%s: Couldn't decode ticket to determine realm for "
- "cell %s.\n",
- progname, cell_to_use);
- } else {
- int len = krb5_princ_realm(context, ticket->server)->length;
- /* This really shouldn't happen. */
- if (len > REALM_SZ-1)
- len = REALM_SZ-1;
-
- strncpy(realm_of_cell, krb5_princ_realm(context, ticket->server)->data, len);
- realm_of_cell[len] = 0;
+ if (retry == 1 && realm_fallback == 0) {
+ /* Only try the realm_of_user once */
+ status = -1;
+ if (dflag)
+ printf("Getting v5 tickets: %s/%s@%s\n", name, instance, realm_of_user);
+ status = get_v5cred(context, name, instance, realm_of_user,
+#ifdef HAVE_KRB4
+ use524 ? &c : NULL,
+#else
+ NULL,
+#endif
+ &v5cred);
+ if (status == 0) {
+ /* we have determined that the client realm
+ * is a valid cell realm
+ */
+ strcpy(realm_of_cell, realm_of_user);
+ }
+ }
- krb5_free_ticket(context, ticket);
+ if (status != 0 && (!retry || retry && strcmp(realm_of_user,realm_of_cell))) {
+ if (dflag)
+ printf("Getting v5 tickets: %s/%s@%s\n", name, instance, realm_of_cell);
+ status = get_v5cred(context, name, instance, realm_of_cell,
+#ifdef HAVE_KRB4
+ use524 ? &c : NULL,
+#else
+ NULL,
+#endif
+ &v5cred);
+ if (!status && !strlen(realm_of_cell))
+ copy_realm_of_ticket(context, realm_of_cell, sizeof(realm_of_cell), v5cred);
}
}
- if (status == KRB5_ERR_HOST_REALM_UNKNOWN) {
+ if (!realm_fallback && status == KRB5_ERR_HOST_REALM_UNKNOWN) {
realm_fallback = 1;
goto try_v5;
} else if (status == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
- if (!realm_of_cell[0]) {
+ if (!realm_fallback && !realm_of_cell[0]) {
realm_fallback = 1;
goto try_v5;
}
NULL,
#endif
&v5cred);
+ if (!status && !strlen(realm_of_cell))
+ copy_realm_of_ticket(context, realm_of_cell, sizeof(realm_of_cell), v5cred);
}
+
if ( status == KRB5KRB_AP_ERR_MSG_TYPE && retry ) {
retry = 0;
realm_fallback = 0;
}
else
{
- if (usev5) {
- if((status = get_v5_user_realm(context, realm_of_user)) != KSUCCESS) {
- fprintf(stderr, "%s: Couldn't determine realm of user: %d\n",
- progname, status);
- return(AKLOG_KERBEROS);
- }
- } else {
+ if (!usev5) {
#ifdef HAVE_KRB4
if ((status = krb_get_tf_realm(TKT_FILE, realm_of_user)) != KSUCCESS)
{
#endif
}
- /* For Khimaira we want to always append the realm to the name */
- if (1 /* strcmp(realm_of_user, realm_of_cell) */)
- {
- strcat(username, "@");
- strcat(username, realm_of_user);
- }
+ /* For Network Identity Manager append the realm to the name */
+ strcat(username, "@");
+ strcat(username, realm_of_user);
ViceIDToUsername(username, realm_of_user, realm_of_cell, cell_to_use,
#ifdef HAVE_KRB4
goto try_krb4;
}
- /* First try Service/Cell@REALM */
- if (r = pkrb5_build_principal(context, &increds.server,
- (int) strlen(RealmName),
- RealmName,
- ServiceName,
- CellName,
- 0)) {
- _reportf(L"krb5_build_principal returns %d", r);
- goto end_krb5;
- }
-
increds.client = client_principal;
increds.times.endtime = 0;
/* Ask for DES since that is what V4 understands */
flags = KRB5_TC_OPENCLOSE;
r = pkrb5_cc_set_flags(context, k5cc, flags);
#endif
- retry_retcred:
- r = pkrb5_get_credentials(context, 0, k5cc, &increds, &k5creds);
- if ((r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
- r == KRB5KRB_ERR_GENERIC /* Heimdal */) &&
- !RealmName[0]) {
- StringCbCopyA(RealmName, sizeof(RealmName),
- afs_realm_of_cell(&ak_cellconfig, TRUE));
-
- pkrb5_free_principal(context, increds.server);
- r = pkrb5_build_principal(context, &increds.server,
- (int) strlen(RealmName),
- RealmName,
- ServiceName,
- CellName,
- 0);
- if (r == 0)
- r = pkrb5_get_credentials(context, 0, k5cc,
- &increds, &k5creds);
- }
- if (r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
- r == KRB5KRB_ERR_GENERIC /* Heimdal */) {
- /* Next try Service@REALM */
- pkrb5_free_principal(context, increds.server);
- r = pkrb5_build_principal(context, &increds.server,
- (int) strlen(RealmName),
- RealmName,
- ServiceName,
- 0);
- if (r == 0)
- r = pkrb5_get_credentials(context, 0, k5cc,
- &increds, &k5creds);
- }
+ if (strlen(realm) != 0) {
+ retry_retcred_1:
+ /* First try Service/Cell@REALM */
+ if (r = pkrb5_build_principal(context, &increds.server,
+ (int) strlen(realm),
+ realm,
+ ServiceName,
+ CellName,
+ 0)) {
+ _reportf(L"krb5_build_principal returns %d", r);
+ goto end_krb5;
+ }
- /* Check to make sure we received a valid ticket; if not remove it
- * and try again. Perhaps there are two service tickets for the
- * same service in the ccache.
- */
- if (r == 0 && k5creds && k5creds->times.endtime < time(NULL)) {
- pkrb5_cc_remove_cred(context, k5cc, 0, k5creds);
- pkrb5_free_creds(context, k5creds);
- k5creds = NULL;
- goto retry_retcred;
- }
+ r = pkrb5_get_credentials(context, 0, k5cc, &increds, &k5creds);
+ if (r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ r == KRB5_ERR_HOST_REALM_UNKNOWN ||
+ r == KRB5KRB_ERR_GENERIC /* Heimdal */) {
+ /* Next try Service@REALM */
+ pkrb5_free_principal(context, increds.server);
+ r = pkrb5_build_principal(context, &increds.server,
+ (int) strlen(realm),
+ realm,
+ ServiceName,
+ 0);
+ if (r == 0)
+ r = pkrb5_get_credentials(context, 0, k5cc,
+ &increds, &k5creds);
+ }
- if (r == 0 && strlen(RealmName) == 0)
- copy_realm_of_ticket(context, realm_of_cell, sizeof(realm_of_cell), k5creds);
+ /* Check to make sure we received a valid ticket; if not remove it
+ * and try again. Perhaps there are two service tickets for the
+ * same service in the ccache.
+ */
+ if (r == 0 && k5creds && k5creds->times.endtime < time(NULL)) {
+ pkrb5_free_principal(context, increds.server);
+ pkrb5_cc_remove_cred(context, k5cc, 0, k5creds);
+ pkrb5_free_creds(context, k5creds);
+ k5creds = NULL;
+ goto retry_retcred_1;
+ }
+ } else {
+ retry_retcred_2:
+ /* First try Service/Cell@_CLIENT_REALM */
+ if (r = pkrb5_build_principal(context, &increds.server,
+ (int) strlen(realm_of_user),
+ realm_of_user,
+ ServiceName,
+ CellName,
+ 0)) {
+ _reportf(L"krb5_build_principal returns %d", r);
+ goto end_krb5;
+ }
+
+ r = pkrb5_get_credentials(context, 0, k5cc, &increds, &k5creds);
+ if (r == 0) {
+ /* the user realm is a valid cell realm */
+ StringCbCopyA(realm_of_cell, sizeof(realm_of_cell), realm_of_user);
+ }
+ if (r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ r == KRB5_ERR_HOST_REALM_UNKNOWN ||
+ r == KRB5KRB_ERR_GENERIC /* Heimdal */) {
+ pkrb5_free_principal(context, increds.server);
+ r = pkrb5_build_principal(context, &increds.server,
+ (int) strlen(realm_of_cell),
+ realm_of_cell,
+ ServiceName,
+ CellName,
+ 0);
+ if (r == 0)
+ r = pkrb5_get_credentials(context, 0, k5cc,
+ &increds, &k5creds);
+ }
+ if ((r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ r == KRB5_ERR_HOST_REALM_UNKNOWN ||
+ r == KRB5KRB_ERR_GENERIC /* Heimdal */) &&
+ strlen(realm_of_cell) == 0) {
+ StringCbCopyA(realm_of_cell, sizeof(realm_of_cell),
+ afs_realm_of_cell(&ak_cellconfig, TRUE));
+
+ pkrb5_free_principal(context, increds.server);
+ r = pkrb5_build_principal(context, &increds.server,
+ (int) strlen(realm_of_cell),
+ realm_of_cell,
+ ServiceName,
+ CellName,
+ 0);
+ if (r == 0)
+ r = pkrb5_get_credentials(context, 0, k5cc,
+ &increds, &k5creds);
+ }
+ if (r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ r == KRB5_ERR_HOST_REALM_UNKNOWN ||
+ r == KRB5KRB_ERR_GENERIC /* Heimdal */) {
+ /* Next try Service@REALM */
+ StringCbCopyA(realm_of_cell, sizeof(realm_of_cell),
+ afs_realm_of_cell(&ak_cellconfig, FALSE));
+
+ pkrb5_free_principal(context, increds.server);
+ r = pkrb5_build_principal(context, &increds.server,
+ (int) strlen(realm_of_cell),
+ realm_of_cell,
+ ServiceName,
+ 0);
+ if (r == 0)
+ r = pkrb5_get_credentials(context, 0, k5cc,
+ &increds, &k5creds);
+ }
+ if ((r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ r == KRB5_ERR_HOST_REALM_UNKNOWN ||
+ r == KRB5KRB_ERR_GENERIC /* Heimdal */) &&
+ strlen(realm_of_cell) == 0) {
+ /* Next try Service@REALM */
+ StringCbCopyA(realm_of_cell, sizeof(realm_of_cell),
+ afs_realm_of_cell(&ak_cellconfig, TRUE));
+
+ pkrb5_free_principal(context, increds.server);
+ r = pkrb5_build_principal(context, &increds.server,
+ (int) strlen(realm_of_cell),
+ realm_of_cell,
+ ServiceName,
+ 0);
+ if (r == 0)
+ r = pkrb5_get_credentials(context, 0, k5cc,
+ &increds, &k5creds);
+ }
+
+ if (r == 0 && strlen(realm_of_cell) == 0)
+ copy_realm_of_ticket(context, realm_of_cell, sizeof(realm_of_cell), k5creds);
+
+ /* Check to make sure we received a valid ticket; if not remove it
+ * and try again. Perhaps there are two service tickets for the
+ * same service in the ccache.
+ */
+ if (r == 0 && k5creds && k5creds->times.endtime < time(NULL)) {
+ pkrb5_free_principal(context, increds.server);
+ pkrb5_cc_remove_cred(context, k5cc, 0, k5creds);
+ pkrb5_free_creds(context, k5creds);
+ k5creds = NULL;
+ goto retry_retcred_2;
+ }
+ }
pkrb5_free_principal(context, increds.server);
pkrb5_free_principal(context, client_principal);