Ejemplo n.º 1
0
/* This routine maintains a list of strings preventing duplication. */
int ll_add_string(linked_list *list, char *string)
{
  ll_node *node;
  char *new_string;

  if (!ll_string_check(list, string))
    {
      node = ll_add_node(list, ll_tail);
      if (node)
	{
	  new_string = strdup(string);
	  if (new_string)
	    ll_add_data(node, new_string);
	  else
	    return LL_FAILURE;
	}
      else
	return LL_FAILURE;
    }
  return LL_SUCCESS;
}
Ejemplo n.º 2
0
/*
* 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
* to.  */
static int auth_to_cell(krb5_context context, char *cell, char *realm)
{
    int status = AKLOG_SUCCESS;
    char username[BUFSIZ];	  /* To hold client username structure */

    char name[ANAME_SZ];	  /* Name of afs key */
    char instance[INST_SZ];	  /* Instance of afs key */
    char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
    char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
    char local_cell[MAXCELLCHARS+1];
    char cell_to_use[MAXCELLCHARS+1]; /* Cell to authenticate to */

    krb5_creds *v5cred = NULL;
#ifdef HAVE_KRB4
    CREDENTIALS c;
#endif
    struct ktc_principal aserver;
    struct ktc_principal aclient;
    struct ktc_token atoken, btoken;
    struct afsconf_cell ak_cellconfig; /* General information about the cell */
    int i;
    int getLinkedCell = 0;

    /* try to avoid an expensive call to get_cellconfig */
    if (cell && ll_string_check(&authedcells, cell))
    {
        if (dflag)
            printf("Already authenticated to %s (or tried to)\n", cell);
        return(AKLOG_SUCCESS);
    }

    memset(name, 0, sizeof(name));
    memset(instance, 0, sizeof(instance));
    memset(realm_of_user, 0, sizeof(realm_of_user));
    memset(realm_of_cell, 0, sizeof(realm_of_cell));
    memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));

    /* NULL or empty cell returns information on local cell */
    if (status = get_cellconfig(cell, &ak_cellconfig, local_cell))
        return(status);

  linkedCell:
    if (getLinkedCell)
        strncpy(cell_to_use, ak_cellconfig.linkedCell, MAXCELLCHARS);
    else
        strncpy(cell_to_use, ak_cellconfig.name, MAXCELLCHARS);
    cell_to_use[MAXCELLCHARS] = 0;

    if (ll_string_check(&authedcells, cell_to_use))
    {
        if (dflag)
            printf("Already authenticated to %s (or tried to)\n", cell_to_use);
        status = AKLOG_SUCCESS;
        goto done2;
    }

    /*
     * Record that we have attempted to log to this cell.  We do this
     * before we try rather than after so that we will not try
     * and fail repeatedly for one cell.
     */
    (void)ll_add_string(&authedcells, cell_to_use);

    if (dflag)
        printf("Authenticating to cell %s.\n", cell_to_use);

    /* We use the afs.<cellname> convention here... */
    strcpy(name, AFSKEY);
    strncpy(instance, cell_to_use, sizeof(instance));
    instance[sizeof(instance)-1] = '\0';

    /*
     * Extract the session key from the ticket file and hand-frob an
     * afs style authenticator.
     */

    if (usev5) 
    { /* using krb5 */
        int retry = 1;
	int realm_fallback = 0;

        if ((status = get_v5_user_realm(context, realm_of_user)) != KSUCCESS) {
            char * msg;
            
            if (pkrb5_get_error_message)
                msg = pkrb5_get_error_message(context, status);
            else
                msg = (char *)error_message(status);
            fprintf(stderr, "%s: Couldn't determine realm of user: %s\n",
                     progname, msg);
            if (pkrb5_free_error_message)
                pkrb5_free_error_message(context, msg);
            status = AKLOG_KERBEROS;
            goto done;
        }

        if ( strchr(name,'.') != NULL ) {
            fprintf(stderr, "%s: Can't support principal names including a dot.\n",
                    progname);
            status = AKLOG_MISC;
            goto done;
        }

      try_v5:
	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 (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);
                }
            }

            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 (!realm_fallback && status == KRB5_ERR_HOST_REALM_UNKNOWN) {
	    realm_fallback = 1;
	    goto try_v5;
	} else if (status == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
	    if (!realm_fallback && !realm_of_cell[0]) {
		realm_fallback = 1;
		goto try_v5;
	    }
            if (dflag)
                printf("Getting v5 tickets: %s@%s\n", name, realm_of_cell);
            status = get_v5cred(context, name, "", 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 == KRB5KRB_AP_ERR_MSG_TYPE && retry ) {
            retry = 0;
	    realm_fallback = 0;
            goto try_v5;
        }       
    }       
    else 
    {
#ifdef HAVE_KRB4
	if (realm && realm[0])
	    strcpy(realm_of_cell, realm);
	else
	    strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig));

	/*
         * Try to obtain AFS tickets.  Because there are two valid service
         * names, we will try both, but trying the more specific first.
         *
         * 	afs.<cell>@<realm>
         * 	afs@<realm>
         */
        if (dflag)
            printf("Getting tickets: %s.%s@%s\n", name, instance, realm_of_cell);
        status = get_cred(name, instance, realm_of_cell, &c);
        if (status == KDC_PR_UNKNOWN)
        {
            if (dflag)
                printf("Getting tickets: %s@%s\n", name, realm_of_cell);
            status = get_cred(name, "", realm_of_cell, &c);
        }
#else
        status = AKLOG_MISC;
        goto done;
#endif
    } 

    if (status != KSUCCESS)
    {
        char * msg = NULL;
        if (dflag)
            printf("Kerberos error code returned by get_cred: %d\n", status);

        if (usev5) {
            if (pkrb5_get_error_message)
                msg = pkrb5_get_error_message(context, status);
            else
                msg = (char *)error_message(status);
        }
#ifdef HAVE_KRB4
        else
            msg = krb_err_text(status);
#endif
        fprintf(stderr, "%s: Couldn't get %s AFS tickets: %s\n",
                 progname, cell_to_use, msg?msg:"(unknown error)");
        if (usev5 && pkrb5_free_error_message)
            pkrb5_free_error_message(context, msg);
        status = AKLOG_KERBEROS;
        goto done;
    }

    strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1);
    strncpy(aserver.instance, AFSINST, MAXKTCNAMELEN - 1);
    strncpy(aserver.cell, cell_to_use, MAXKTCREALMLEN - 1);

    if (usev5 && !use524) {
        /* This code inserts the entire K5 ticket into the token
         * No need to perform a krb524 translation which is
         * commented out in the code below
         */
        char * p;
        int len;
        
        len = min(v5cred->client->data[0].length,MAXKTCNAMELEN - 1);
        strncpy(username, v5cred->client->data[0].data, len);
        username[len] = '\0';

        if ( v5cred->client->length > 1 ) {
            strcat(username, ".");
            p = username + strlen(username);
            len = min(v5cred->client->data[1].length, (unsigned int)(MAXKTCNAMELEN - strlen(username) - 1));
            strncpy(p, v5cred->client->data[1].data, len);
            p[len] = '\0';
        }

        memset(&atoken, '\0', sizeof(atoken));
        atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
        atoken.startTime = v5cred->times.starttime;
        atoken.endTime = v5cred->times.endtime;
        memcpy(&atoken.sessionKey, v5cred->keyblock.contents, v5cred->keyblock.length);
        atoken.ticketLen = v5cred->ticket.length;
        memcpy(atoken.ticket, v5cred->ticket.data, atoken.ticketLen);
    } else {
#ifdef HAVE_KRB4
        strcpy (username, c.pname);
        if (c.pinst[0])
        {
            strcat(username, ".");
            strcat(username, c.pinst);
        }

        atoken.kvno = c.kvno;
        atoken.startTime = c.issue_date;
        /* ticket lifetime is in five-minutes blocks. */
        atoken.endTime = c.issue_date + ((unsigned char)c.lifetime * 5 * 60);

        memcpy(&atoken.sessionKey, c.session, 8);
        atoken.ticketLen = c.ticket_st.length;
        memcpy(atoken.ticket, c.ticket_st.dat, atoken.ticketLen);
#else
        status = AKLOG_MISC;
        goto done;
#endif
    }

    if (!force &&
         !ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient) &&
         atoken.kvno == btoken.kvno &&
         atoken.ticketLen == btoken.ticketLen &&
         !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
         !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
    {       
        if (dflag)
            printf("Identical tokens already exist; skipping.\n");
        status = AKLOG_SUCCESS;
        goto done2;
    }

    if (noprdb)
    {
        if (dflag)
            printf("Not resolving name %s to id (-noprdb set)\n", username);
    }       
    else    
    {
        if (!usev5) {
#ifdef HAVE_KRB4
            if ((status = krb_get_tf_realm(TKT_FILE, realm_of_user)) != KSUCCESS)
            {
                fprintf(stderr, "%s: Couldn't determine realm of user: %s)",
                         progname, krb_err_text(status));
                status = AKLOG_KERBEROS;
                goto done;
            }
#else
            status = AKLOG_MISC;
            goto done;
#endif
        }

        /* 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
                          &c, 
#else
                          NULL,
#endif
                          &status, &aclient, &aserver, &atoken);
    }

    if (dflag)
        printf("Set username to %s\n", username);

    /* Reset the "aclient" structure before we call ktc_SetToken.
     * This structure was first set by the ktc_GetToken call when
     * we were comparing whether identical tokens already existed.
     */
    strncpy(aclient.name, username, MAXKTCNAMELEN - 1);
    strcpy(aclient.instance, "");
    
    if (usev5 && !use524) {
        int len = min(v5cred->client->realm.length,MAXKTCNAMELEN - 1);
        strncpy(aclient.cell, v5cred->client->realm.data, len);
        aclient.cell[len] = '\0';
    } 
#ifdef HAVE_KRB4
    else
	strncpy(aclient.cell, c.realm, MAXKTCREALMLEN - 1);
#endif

    for ( i=0; aclient.cell[i]; i++ ) {
        if ( islower(aclient.cell[i]) )
            aclient.cell[i] = toupper(aclient.cell[i]);
    }

    if (dflag)
        printf("Getting tokens.\n");
    if (status = ktc_SetToken(&aserver, &atoken, &aclient, 0))
    {
        afs_com_err(progname, status,
                     "while obtaining tokens for cell %s\n",
                     cell_to_use);
        status = AKLOG_TOKEN;
    }

  done2:
    if (ak_cellconfig.linkedCell && !getLinkedCell) {
        getLinkedCell = 1;
        goto linkedCell;
    }

  done:
#if 0
    /* 
     * intentionally leak the linkedCell field because it was allocated
     * using a different C RTL version.
     */
    if (ak_cellconfig.linkedCell)
        free(ak_cellconfig.linkedCell);
#endif
    return(status);
}
Ejemplo n.º 3
0
/*
 * 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
 * to.  */
static int auth_to_cell(char *cell, char *realm)
{
  int status = AKLOG_SUCCESS;
  char username[BUFSIZ];	/* To hold client username structure */
  long viceId;			/* AFS uid of user */

  char name[ANAME_SZ];		/* Name of afs key */
  char instance[INST_SZ];	/* Instance of afs key */
  char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
  char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
  char local_cell[MAXCELLCHARS+1];
  char cell_to_use[MAXCELLCHARS+1]; /* Cell to authenticate to */

  int i,j;

  CREDENTIALS c;
  struct ktc_principal aserver;
  struct ktc_principal aclient;
  struct ktc_token atoken, btoken;

  /* try to avoid an expensive call to get_cellconfig */
  if (cell && ll_string_check(&authedcells, cell))
    {
      if (dflag)
	printf("Already authenticated to %s (or tried to)\n", cell);
      return(AKLOG_SUCCESS);
    }

  memset(name, 0, sizeof(name));
  memset(instance, 0, sizeof(instance));
  memset(realm_of_user, 0, sizeof(realm_of_user));
  memset(realm_of_cell, 0, sizeof(realm_of_cell));

  /* NULL or empty cell returns information on local cell */
  if (status = get_cellconfig(cell, &ak_cellconfig, local_cell))
    return(status);

  strncpy(cell_to_use, ak_cellconfig.name, MAXCELLCHARS);
  cell_to_use[MAXCELLCHARS] = 0;

  if (ll_string_check(&authedcells, cell_to_use))
    {
      if (dflag)
	printf("Already authenticated to %s (or tried to)\n", cell_to_use);
      return(AKLOG_SUCCESS);
    }

  /*
   * Record that we have attempted to log to this cell.  We do this
   * before we try rather than after so that we will not try
   * and fail repeatedly for one cell.
   */
  (void)ll_add_string(&authedcells, cell_to_use);

  if (dflag)
    printf("Authenticating to cell %s.\n", cell_to_use);

  if (realm && realm[0])
    strcpy(realm_of_cell, realm);
  else
    strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig));

  /* We use the afs.<cellname> convention here... */
  strcpy(name, AFSKEY);
  strncpy(instance, cell_to_use, sizeof(instance));
  instance[sizeof(instance)-1] = '\0';

  /*
   * Extract the session key from the ticket file and hand-frob an
   * afs style authenticator.
   */

  /*
   * Try to obtain AFS tickets.  Because there are two valid service
   * names, we will try both, but trying the more specific first.
   *
   * 	afs.<cell>@<realm>
   * 	afs@<realm>
   */
  if (dflag)
    printf("Getting tickets: %s.%s@%s\n", name, instance, realm_of_cell);
  status = get_cred(name, instance, realm_of_cell, &c);
  if (status == KDC_PR_UNKNOWN)
    {
      if (dflag)
	printf("Getting tickets: %s@%s\n", name, realm_of_cell);
      status = get_cred(name, "", realm_of_cell, &c);
    }

  if (status != KSUCCESS)
    {
      if (dflag)
	printf("Kerberos error code returned by get_cred: %d\n", status);
      fprintf(stderr, "%s: Couldn't get %s AFS tickets: %s\n",
	      progname, cell_to_use, krb_err_txt[status]);
      return(AKLOG_KERBEROS);
    }

  strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1);
  strncpy(aserver.instance, AFSINST, MAXKTCNAMELEN - 1);
  strncpy(aserver.cell, cell_to_use, MAXKTCREALMLEN - 1);

  strcpy (username, c.pname);
  if (c.pinst[0])
    {
      strcat(username, ".");
      strcat(username, c.pinst);
    }

  atoken.kvno = c.kvno;
  atoken.startTime = c.issue_date;
  /* ticket lifetime is in five-minutes blocks. */
  atoken.endTime = c.issue_date + ((unsigned char)c.lifetime * 5 * 60);
  memcpy(&atoken.sessionKey, c.session, 8);
  atoken.ticketLen = c.ticket_st.length;
  memcpy(atoken.ticket, c.ticket_st.dat, atoken.ticketLen);

  if (!force &&
      !ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient) &&
      atoken.kvno == btoken.kvno &&
      atoken.ticketLen == btoken.ticketLen &&
      !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
      !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
    {
      if (dflag)
	printf("Identical tokens already exist; skipping.\n");
      return 0;
    }

  if (noprdb)
    {
      if (dflag)
	printf("Not resolving name %s to id (-noprdb set)\n", username);
    }
  else
    {
      if ((status = krb_get_tf_realm(TKT_FILE, realm_of_user)) != KSUCCESS)
	{
	  fprintf(stderr, "%s: Couldn't determine realm of user: %s)",
		  progname, krb_err_txt[status]);
	  return(AKLOG_KERBEROS);
	}
      if (strcmp(realm_of_user, realm_of_cell))
	{
	  strcat(username, "@");
	  strcat(username, realm_of_user);
	}

      if (dflag)
	printf("About to resolve name %s to id\n", username);

      if (!pr_Initialize (0, AFSDIR_CLIENT_ETC_DIRPATH, aserver.cell))
	status = pr_SNameToId (username, &viceId);

      if (dflag)
	{
	  if (status)
	    printf("Error %d\n", status);
	  else
	    printf("Id %d\n", viceId);
	}

      /*
       * This is a crock, but it is Transarc's crock, so
       * we have to play along in order to get the
       * functionality.  The way the afs id is stored is
       * as a string in the username field of the token.
       * Contrary to what you may think by looking at
       * the code for tokens, this hack (AFS ID %d) will
       * not work if you change %d to something else.
       */
      if ((status == 0) && (viceId != ANONYMOUSID))
	sprintf (username, "AFS ID %d", viceId);
    }

  if (dflag)
    printf("Set username to %s\n", username);

  /* Reset the "aclient" structure before we call ktc_SetToken.
   * This structure was first set by the ktc_GetToken call when
   * we were comparing whether identical tokens already existed.
   */
  strncpy(aclient.name, username, MAXKTCNAMELEN - 1);
  strcpy(aclient.instance, "");
  strncpy(aclient.cell, c.realm, MAXKTCREALMLEN - 1);

  if (dflag)
    printf("Getting tokens.\n");
  if (status = ktc_SetToken(&aserver, &atoken, &aclient, 0))
    {
      fprintf(stderr,
	      "%s: unable to obtain tokens for cell %s (status: %d).\n",
	      progname, cell_to_use, status);
      status = AKLOG_TOKEN;
    }

  return(status);
}