Ejemplo n.º 1
0
void
auth_is(unsigned char *data, int cnt)
{
	Authenticator *ap;

	if (cnt < 2)
		return;

	if (data[0] == AUTHTYPE_NULL) {
		auth_finished(0, AUTH_REJECT);
		return;
	}

	if ((ap = findauthenticator(data[0], data[1]))) {
		if (ap->is)
			(*ap->is)(ap, data+2, cnt-2);
	} else if (auth_debug_mode)
		printf(">>>%s: Invalid authentication in IS: %d\r\n",
			Name, *data);
}
Ejemplo n.º 2
0
void recv_handler_done (BSocksClient *o, int data_len)
{
    ASSERT(data_len >= 0)
    ASSERT(data_len <= o->control.recv_total - o->control.recv_len)
    DebugObject_Access(&o->d_obj);
    
    o->control.recv_len += data_len;
    
    if (o->control.recv_len < o->control.recv_total) {
        do_receive(o);
        return;
    }
    
    switch (o->state) {
        case STATE_SENT_HELLO: {
            BLog(BLOG_DEBUG, "received hello");
            
            struct socks_server_hello imsg;
            memcpy(&imsg, o->buffer, sizeof(imsg));
            
            if (ntoh8(imsg.ver) != SOCKS_VERSION) {
                BLog(BLOG_NOTICE, "wrong version");
                goto fail;
            }
            
            size_t auth_index;
            for (auth_index = 0; auth_index < o->num_auth_info; auth_index++) {
                if (o->auth_info[auth_index].auth_type == ntoh8(imsg.method)) {
                    break;
                }
            }
            
            if (auth_index == o->num_auth_info) {
                BLog(BLOG_NOTICE, "server didn't accept any authentication method");
                goto fail;
            }
            
            const struct BSocksClient_auth_info *ai = &o->auth_info[auth_index];
            
            switch (ai->auth_type) {
                case SOCKS_METHOD_NO_AUTHENTICATION_REQUIRED: {
                    BLog(BLOG_DEBUG, "no authentication");
                    
                    auth_finished(o);
                } break;
                
                case SOCKS_METHOD_USERNAME_PASSWORD: {
                    BLog(BLOG_DEBUG, "password authentication");
                    
                    if (ai->password.username_len == 0 || ai->password.username_len > 255 ||
                        ai->password.password_len == 0 || ai->password.password_len > 255
                    ) {
                        BLog(BLOG_NOTICE, "invalid username/password length");
                        goto fail;
                    }
                    
                    // allocate password packet
                    bsize_t size = bsize_fromsize(1 + 1 + ai->password.username_len + 1 + ai->password.password_len);
                    if (!reserve_buffer(o, size)) {
                        goto fail;
                    }
                    
                    // write password packet
                    char *ptr = o->buffer;
                    *ptr++ = 1;
                    *ptr++ = ai->password.username_len;
                    memcpy(ptr, ai->password.username, ai->password.username_len);
                    ptr += ai->password.username_len;
                    *ptr++ = ai->password.password_len;
                    memcpy(ptr, ai->password.password, ai->password.password_len);
                    ptr += ai->password.password_len;
                    
                    // start sending
                    PacketPassInterface_Sender_Send(o->control.send_if, (uint8_t *)o->buffer, size.value);
                    
                    // set state
                    o->state = STATE_SENDING_PASSWORD;
                } break;
                
                default: ASSERT(0);
            }
        } break;
        
        case STATE_SENT_REQUEST: {
            BLog(BLOG_DEBUG, "received reply header");
            
            struct socks_reply_header imsg;
            memcpy(&imsg, o->buffer, sizeof(imsg));
            
            if (ntoh8(imsg.ver) != SOCKS_VERSION) {
                BLog(BLOG_NOTICE, "wrong version");
                goto fail;
            }
            
            if (ntoh8(imsg.rep) != SOCKS_REP_SUCCEEDED) {
                BLog(BLOG_NOTICE, "reply not successful");
                goto fail;
            }
            
            int addr_len;
            switch (ntoh8(imsg.atyp)) {
                case SOCKS_ATYP_IPV4:
                    addr_len = sizeof(struct socks_addr_ipv4);
                    break;
                case SOCKS_ATYP_IPV6:
                    addr_len = sizeof(struct socks_addr_ipv6);
                    break;
                default:
                    BLog(BLOG_NOTICE, "reply has unknown address type");
                    goto fail;
            }
            
            // receive the rest of the reply
            start_receive(o, (uint8_t *)o->buffer + sizeof(imsg), addr_len);
            
            // set state
            o->state = STATE_RECEIVED_REPLY_HEADER;
        } break;
        
        case STATE_SENT_PASSWORD: {
            BLog(BLOG_DEBUG, "received password reply");
            
            if (o->buffer[0] != 1) {
                BLog(BLOG_NOTICE, "password reply has unknown version");
                goto fail;
            }
            
            if (o->buffer[1] != 0) {
                BLog(BLOG_NOTICE, "password reply is negative");
                goto fail;
            }
            
            auth_finished(o);
        } break;
        
        case STATE_RECEIVED_REPLY_HEADER: {
            BLog(BLOG_DEBUG, "received reply rest");
            
            // free buffer
            BFree(o->buffer);
            o->buffer = NULL;
            
            // free control I/O
            free_control_io(o);
            
            // init up I/O
            init_up_io(o);
            
            // set state
            o->state = STATE_UP;
            
            // call handler
            o->handler(o->user, BSOCKSCLIENT_EVENT_UP);
            return;
        } break;
        
        default:
            ASSERT(0);
    }
    
    return;
    
fail:
    report_error(o, BSOCKSCLIENT_EVENT_ERROR);
}
Ejemplo n.º 3
0
void wontoption(int option) {
    /*
     * Process client input.
     */

    DIAG(TD_OPTIONS, printoption("td: recv wont", option));

    if (do_dont_resp[option]) {
        do_dont_resp[option]--;
        if (do_dont_resp[option] && his_state_is_wont(option))
            do_dont_resp[option]--;
    }
    if (do_dont_resp[option] == 0) {
        if (his_want_state_is_will(option)) {
            /* it is always ok to change to negative state */
            switch (option) {
            case TELOPT_ECHO:
                not42 = 1; /* doesn't seem to be a 4.2 system */
                break;

            case TELOPT_BINARY:
                init_termbuf();
                tty_binaryin(0);
                set_termbuf();
                break;

#ifdef LINEMODE
            case TELOPT_LINEMODE:
#ifdef KLUDGELINEMODE
                /*
                 * If real linemode is supported, then client is
                 * asking to turn linemode off.
                 */
                if (lmodetype != REAL_LINEMODE)
                    break;
                lmodetype = KLUDGE_LINEMODE;
# endif	/* KLUDGELINEMODE */
                clientstat(TELOPT_LINEMODE, WONT, 0);
                break;
#endif	/* LINEMODE */

            case TELOPT_TM:
                /*
                 * If we get a WONT TM, and had sent a DO TM,
                 * don't respond with a DONT TM, just leave it
                 * as is.  Short circut the state machine to
                 * achive this.
                 */
                set_his_want_state_wont(TELOPT_TM);
                return;

            case TELOPT_LFLOW:
                /*
                 * If we are not going to support flow control
                 * option, then let peer know that we can't
                 * change the flow control characters.
                 */
                slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
                slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE;
                slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
                slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE;
                break;

#if defined(AUTHENTICATE)
            case TELOPT_AUTHENTICATION:
                auth_finished(0, AUTH_REJECT);
                break;
#endif

            /*
             * For options that we might spin waiting for
             * sub-negotiation, if the client turns off the
             * option rather than responding to the request,
             * we have to treat it here as if we got a response
             * to the sub-negotiation, (by updating the timers)
             * so that we'll break out of the loop.
             */
            case TELOPT_TTYPE:
                settimer(ttypesubopt);
                break;

            case TELOPT_TSPEED:
                settimer(tspeedsubopt);
                break;

            case TELOPT_XDISPLOC:
                settimer(xdisplocsubopt);
                break;

            case TELOPT_ENVIRON:
                settimer(environsubopt);
                break;

            default:
                break;
            }
            set_his_want_state_wont(option);
            if (his_state_is_will(option)) send_dont(option, 0);
        }
        else {
            switch (option) {
            case TELOPT_TM:
#if defined(LINEMODE) && defined(KLUDGELINEMODE)
                if (lmodetype < REAL_LINEMODE) {
                    lmodetype = NO_LINEMODE;
                    clientstat(TELOPT_LINEMODE, WONT, 0);
                    send_will(TELOPT_SGA, 1);
                    send_will(TELOPT_ECHO, 1);
                }
#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
                break;

#if	defined(AUTHENTICATE)
            case TELOPT_AUTHENTICATION:
                auth_finished(0, AUTH_REJECT);
                break;
#endif
            default:
                break;
            }
        }
    }
}  /* end of wontoption */
Ejemplo n.º 4
0
/* ARGSUSED */
static void
auth_intr(int sig __unused)
{
	auth_finished(0, AUTH_REJECT);
}
Ejemplo n.º 5
0
/*
 * This is called when an AUTH SEND is received.
 * It should never arrive on the server side (as only the server can
 * send an AUTH SEND).
 * You should probably respond to it if you can...
 *
 * If you want to respond to the types out of order (i.e. even
 * if he sends  LOGIN KERBEROS and you support both, you respond
 * with KERBEROS instead of LOGIN (which is against what the
 * protocol says)) you will have to hack this code...
 */
void
auth_send(unsigned char *data, int cnt)
{
	Authenticator *ap;
	static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
					    TELQUAL_IS, AUTHTYPE_NULL, 0,
					    IAC, SE };
	if (Server) {
		if (auth_debug_mode) {
			printf(">>>%s: auth_send called!\r\n", Name);
		}
		return;
	}

	if (auth_debug_mode) {
		printf(">>>%s: auth_send got:", Name);
		printd(data, cnt); printf("\r\n");
	}

	/*
	 * Save the data, if it is new, so that we can continue looking
	 * at it if the authorization we try doesn't work
	 */
	if (data < _auth_send_data ||
	    data > _auth_send_data + sizeof(_auth_send_data)) {
		auth_send_cnt = (size_t)cnt > sizeof(_auth_send_data)
					? sizeof(_auth_send_data)
					: cnt;
		memmove((void *)_auth_send_data, (void *)data, auth_send_cnt);
		auth_send_data = _auth_send_data;
	} else {
		/*
		 * This is probably a no-op, but we just make sure
		 */
		auth_send_data = data;
		auth_send_cnt = cnt;
	}
	while ((auth_send_cnt -= 2) >= 0) {
		if (auth_debug_mode)
			printf(">>>%s: He supports %d\r\n",
				Name, *auth_send_data);
		if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
			ap = findauthenticator(auth_send_data[0],
					       auth_send_data[1]);
			if (ap && ap->send) {
				if (auth_debug_mode)
					printf(">>>%s: Trying %d %d\r\n",
						Name, auth_send_data[0],
							auth_send_data[1]);
				if ((*ap->send)(ap)) {
					/*
					 * Okay, we found one we like
					 * and did it.
					 * we can go home now.
					 */
					if (auth_debug_mode)
						printf(">>>%s: Using type %d\r\n",
							Name, *auth_send_data);
					auth_send_data += 2;
					return;
				}
			}
			/* else
			 *	just continue on and look for the
			 *	next one if we didn't do anything.
			 */
		}
		auth_send_data += 2;
	}
	net_write(str_none, sizeof(str_none));
	printsub('>', &str_none[2], sizeof(str_none) - 2);
	if (auth_debug_mode)
		printf(">>>%s: Sent failure message\r\n", Name);
	auth_finished(0, AUTH_REJECT);
}
Ejemplo n.º 6
0
void
kerberos5_is(Authenticator *ap, unsigned char *data, int cnt)
{
    krb5_error_code ret;
    krb5_data outbuf;
    krb5_keyblock *key_block;
    char *name;
    krb5_principal server;
    krb5_authenticator authenticator;
    int zero = 0;

    if (cnt-- < 1)
	return;
    switch (*data++) {
    case KRB_AUTH:
	auth.data = (char *)data;
	auth.length = cnt;

	auth_context = NULL;

	ret = krb5_auth_con_init (context, &auth_context);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	ret = krb5_auth_con_setaddrs_from_fd (context,
					      auth_context,
					      &zero);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	ret = krb5_sock_to_principal (context,
				      0,
				      "host",
				      KRB5_NT_SRV_HST,
				      &server);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_sock_to_principal failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	ret = krb5_rd_req(context,
			  &auth_context,
			  &auth, 
			  server,
			  NULL,
			  NULL,
			  &ticket);
	krb5_free_principal (context, server);

	if (ret) {
	    char *errbuf;

	    asprintf(&errbuf,
		     "Read req failed: %s",
		     krb5_get_err_text(context, ret));
	    Data(ap, KRB_REJECT, errbuf, -1);
	    if (auth_debug_mode)
		printf("%s\r\n", errbuf);
	    free (errbuf);
	    return;
	}

	ret = krb5_auth_con_getkey(context, auth_context, &key_block);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_getkey failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_con_getkey failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}
	
	ret = krb5_auth_getauthenticator (context,
					  auth_context,
					  &authenticator);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_getauthenticator failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_getauthenticator failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	if (authenticator->cksum) {
	    char foo[2];

	    foo[0] = ap->type;
	    foo[1] = ap->way;

	    ret = krb5_verify_checksum (context,
					foo,
					sizeof(foo),
					key_block,
					authenticator->cksum);
	    if (ret) {
		Data(ap, KRB_REJECT, "No checksum", -1);
		if (auth_debug_mode)
		    printf ("No checksum\r\n");
		krb5_free_authenticator (context,
					 &authenticator);
		
		return;
	    }
	}
	krb5_free_authenticator (context,
				 &authenticator);

	ret = krb5_auth_con_getremotesubkey (context,
					     auth_context,
					     &key_block);

	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_con_getremotesubkey failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
	    ret = krb5_mk_rep(context, &auth_context, &outbuf);
	    if (ret) {
		Data(ap, KRB_REJECT,
		     "krb5_mk_rep failed", -1);
		auth_finished(ap, AUTH_REJECT);
		if (auth_debug_mode)
		    printf("Kerberos V5: "
			   "krb5_mk_rep failed (%s)\r\n",
			   krb5_get_err_text(context, ret));
		return;
	    }
	    Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
	}
	if (krb5_unparse_name(context, ticket->client, &name))
	    name = 0;

	if(UserNameRequested && krb5_kuserok(context,
					     ticket->client,
					     UserNameRequested)) {
	    Data(ap, KRB_ACCEPT, name, name ? -1 : 0);
	    if (auth_debug_mode) {
		printf("Kerberos5 identifies him as ``%s''\r\n",
		       name ? name : "");
	    }

	    if(key_block->keytype == KEYTYPE_DES) {
		Session_Key skey;

		skey.type = SK_DES;
		skey.length = 8;
		skey.data = key_block->keyvalue.data;
		encrypt_session_key(&skey, 0);
	    }

	} else {
	    char *msg;

	    asprintf (&msg, "user `%s' is not authorized to "
		      "login as `%s'", 
		      name ? name : "<unknown>",
		      UserNameRequested ? UserNameRequested : "<nobody>");
	    if (msg == NULL)
		Data(ap, KRB_REJECT, NULL, 0);
	    else {
		Data(ap, KRB_REJECT, (void *)msg, -1);
		free(msg);
	    }
	}
	auth_finished(ap, AUTH_USER);

	krb5_free_keyblock_contents(context, key_block);
	
	break;
#ifdef	FORWARD
    case KRB_FORWARD: {
	struct passwd *pwd;
	char ccname[1024];	/* XXX */
	krb5_data inbuf;
	krb5_ccache ccache;
	inbuf.data = (char *)data;
	inbuf.length = cnt;

	pwd = getpwnam (UserNameRequested);
	if (pwd == NULL)
	    break;

	snprintf (ccname, sizeof(ccname),
		  "FILE:/tmp/krb5cc_%u", pwd->pw_uid);

	ret = krb5_cc_resolve (context, ccname, &ccache);
	if (ret) {
	    if (auth_debug_mode)
		printf ("Kerberos V5: could not get ccache: %s\r\n",
			krb5_get_err_text(context, ret));
	    break;
	}

	ret = krb5_cc_initialize (context,
				  ccache,
				  ticket->client);
	if (ret) {
	    if (auth_debug_mode)
		printf ("Kerberos V5: could not init ccache: %s\r\n",
			krb5_get_err_text(context, ret));
	    break;
	}

	ret = krb5_rd_cred (context,
			    auth_context,
			    ccache,
			    &inbuf);
	if(ret) {
	    char *errbuf;

	    asprintf (&errbuf,
		      "Read forwarded creds failed: %s",
		      krb5_get_err_text (context, ret));
	    if(errbuf == NULL)
		Data(ap, KRB_FORWARD_REJECT, NULL, 0);
	    else
		Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
	    if (auth_debug_mode)
		printf("Could not read forwarded credentials: %s\r\n",
		       errbuf);
	    free (errbuf);
	} else
	    Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
	chown (ccname + 5, pwd->pw_uid, -1);
	if (auth_debug_mode)
	    printf("Forwarded credentials obtained\r\n");
	break;
    }
#endif	/* FORWARD */
    default:
	if (auth_debug_mode)
	    printf("Unknown Kerberos option %d\r\n", data[-1]);
	Data(ap, KRB_REJECT, 0, 0);
	break;
    }
}
Ejemplo n.º 7
0
void
kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt)
{
    static int mutual_complete = 0;

    if (cnt-- < 1)
	return;
    switch (*data++) {
    case KRB_REJECT:
	if (cnt > 0) {
	    printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n",
		   cnt, data);
	} else
	    printf("[ Kerberos V5 refuses authentication ]\r\n");
	auth_send_retry();
	return;
    case KRB_ACCEPT: {
	krb5_error_code ret;
	Session_Key skey;
	krb5_keyblock *keyblock;
	
	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
	    !mutual_complete) {
	    printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n");
	    auth_send_retry();
	    return;
	}
	if (cnt)
	    printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data);
	else
	    printf("[ Kerberos V5 accepts you ]\r\n");
	      
	ret = krb5_auth_con_getlocalsubkey (context,
					    auth_context,
					    &keyblock);
	if (ret)
	    ret = krb5_auth_con_getkey (context,
					auth_context,
					&keyblock);
	if(ret) {
	    printf("[ krb5_auth_con_getkey: %s ]\r\n",
		   krb5_get_err_text(context, ret));
	    auth_send_retry();
	    return;
	}
	      
	skey.type = SK_DES;
	skey.length = 8;
	skey.data = keyblock->keyvalue.data;
	encrypt_session_key(&skey, 0);
	krb5_free_keyblock_contents (context, keyblock);
	auth_finished(ap, AUTH_USER);
#ifdef	FORWARD
	if (forward_flags & OPTS_FORWARD_CREDS)
	    kerberos5_forward(ap);
#endif	/* FORWARD */
	break;
    }
    case KRB_RESPONSE:
	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
	    /* the rest of the reply should contain a krb_ap_rep */
	  krb5_ap_rep_enc_part *reply;
	  krb5_data inbuf;
	  krb5_error_code ret;
	    
	  inbuf.length = cnt;
	  inbuf.data = (char *)data;

	  ret = krb5_rd_rep(context, auth_context, &inbuf, &reply);
	  if (ret) {
	      printf("[ Mutual authentication failed: %s ]\r\n",
		     krb5_get_err_text (context, ret));
	      auth_send_retry();
	      return;
	  }
	  krb5_free_ap_rep_enc_part(context, reply);
	  mutual_complete = 1;
	}
	return;
#ifdef	FORWARD
    case KRB_FORWARD_ACCEPT:
	printf("[ Kerberos V5 accepted forwarded credentials ]\r\n");
	return;
    case KRB_FORWARD_REJECT:
	printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n",
	       cnt, data);
	return;
#endif	/* FORWARD */
    default:
	if (auth_debug_mode)
	    printf("Unknown Kerberos option %d\r\n", data[-1]);
	return;
    }
}
Ejemplo n.º 8
0
/*
 * This is called when an AUTH SEND is received.
 * It should never arrive on the server side (as only the server can
 * send an AUTH SEND).
 * You should probably respond to it if you can...
 *
 * If you want to respond to the types out of order (i.e. even
 * if he sends  LOGIN KERBEROS and you support both, you respond
 * with KERBEROS instead of LOGIN (which is against what the
 * protocol says)) you will have to hack this code...
 */
void
auth_send (unsigned char *data, int cnt)
{
  TN_Authenticator *ap;
  static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
    TELQUAL_IS, AUTHTYPE_NULL, 0,
    IAC, SE
  };
  if (Server)
    {
      if (auth_debug_mode)
	{
	  printf (">>>%s: auth_send called!\r\n", Name);
	}
      return;
    }

  if (auth_debug_mode)
    {
      printf (">>>%s: auth_send got:", Name);
      printd (data, cnt);
      printf ("\r\n");
    }

  /*
   * Save the data, if it is new, so that we can continue looking
   * at it if the authorization we try doesn't work
   */
  if (data < _auth_send_data ||
      data > _auth_send_data + sizeof (_auth_send_data))
    {
      auth_send_cnt = cnt > sizeof (_auth_send_data)
	? sizeof (_auth_send_data) : cnt;
      memmove ((void *) _auth_send_data, (void *) data, auth_send_cnt);
      auth_send_data = _auth_send_data;
    }
  else
    {
      /*
       * This is probably a no-op, but we just make sure
       */
      auth_send_data = data;
      auth_send_cnt = cnt;
    }
  while ((auth_send_cnt -= 2) >= 0)
    {
      if (auth_debug_mode)
	printf (">>>%s: He supports %s (%d) %s (%d)\r\n",
		Name, AUTHTYPE_NAME_OK (auth_send_data[0]) ?
		AUTHTYPE_NAME (auth_send_data[0]) :
		"unknown",
		auth_send_data[0],
		auth_send_data[1] &
		AUTH_HOW_MASK &
		AUTH_HOW_MUTUAL ? "MUTUAL" : "ONEWAY", auth_send_data[1]);
      if ((i_support & ~i_wont_support) & typemask (*auth_send_data))
	{
	  ap = findauthenticator (auth_send_data[0], auth_send_data[1]);
	  if (ap && ap->send)
	    {
	      if (auth_debug_mode)
		printf (">>>%s: Trying %s (%d) %s (%d)\r\n",
			Name,
			AUTHTYPE_NAME_OK (auth_send_data[0]) ?
			AUTHTYPE_NAME (auth_send_data[0]) :
			"unknown",
			auth_send_data[0],
			auth_send_data[1] &
			AUTH_HOW_MASK &
			AUTH_HOW_MUTUAL ?
			"MUTUAL" : "ONEWAY", auth_send_data[1]);
	      if ((*ap->send) (ap))
		{
		  /*
		   * Okay, we found one we like
		   * and did it.
		   * we can go home now.
		   */
		  if (auth_debug_mode)
		    printf (">>>%s: Using type %s (%d)\r\n",
			    Name,
			    AUTHTYPE_NAME_OK (*auth_send_data) ?
			    AUTHTYPE_NAME (*auth_send_data) :
			    "unknown", *auth_send_data);
		  auth_send_data += 2;
		  return;
		}
	    }
	  /* else
	   *      just continue on and look for the
	   *      next one if we didn't do anything.
	   */
	}
      auth_send_data += 2;
    }
  net_write (str_none, sizeof (str_none));
  printsub ('>', &str_none[2], sizeof (str_none) - 2);
  if (auth_debug_mode)
    printf (">>>%s: Sent failure message\r\n", Name);
  auth_finished (0, AUTH_REJECT);
# ifdef KANNAN
  /*
   *  We requested strong authentication, however no mechanisms worked.
   *  Therefore, exit on client end.
   */
  printf ("Unable to securely authenticate user ... exit\n");
  exit (EXIT_SUCCESS);
# endif	/* KANNAN */
}
Ejemplo n.º 9
0
static void
auth_intr (int sig _GL_UNUSED_PARAMETER)
{
  auth_finished (0, AUTH_REJECT);
}
Ejemplo n.º 10
0
void
kerberos4_reply(Authenticator *ap, unsigned char *data, int cnt)
{
    Session_Key skey;

    if (cnt-- < 1)
	return;
    switch (*data++) {
    case KRB_REJECT:
	if(auth_done){ /* XXX Ick! */
	    printf("[ Kerberos V4 received unknown opcode ]\r\n");
	}else{
	    printf("[ Kerberos V4 refuses authentication ");
	    if (cnt > 0) 
		printf("because %.*s ", cnt, data);
	    printf("]\r\n");
	    auth_send_retry();
	}
	return;
    case KRB_ACCEPT:
	printf("[ Kerberos V4 accepts you ]\r\n");
	auth_done = 1;
	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
	    /*
	     * Send over the encrypted challenge.
	     */
	    Data(ap, KRB_CHALLENGE, session_key, 
		 sizeof(session_key));
	    des_ecb_encrypt(&session_key, &session_key, sched, 1);
	    skey.type = SK_DES;
	    skey.length = 8;
	    skey.data = session_key;
	    encrypt_session_key(&skey, 0);
#if 0
	    kerberos4_forward(ap);
#endif
	    return;
	}
	auth_finished(ap, AUTH_USER);
	return;
    case KRB_RESPONSE:
	/* make sure the response is correct */
	if ((cnt != sizeof(des_cblock)) ||
	    (memcmp(data, challenge, sizeof(challenge)))){
	    printf("[ Kerberos V4 challenge failed!!! ]\r\n");
	    auth_send_retry();
	    return;
	}
	printf("[ Kerberos V4 challenge successful ]\r\n");
	auth_finished(ap, AUTH_USER);
	break;
    case KRB_FORWARD_ACCEPT:
	printf("[ Kerberos V4 accepted forwarded credentials ]\r\n");
	break;
    case KRB_FORWARD_REJECT:
	printf("[ Kerberos V4 rejected forwarded credentials: `%.*s']\r\n",
	       cnt, data);
	break;
    default:
	if (auth_debug_mode)
	    printf("Unknown Kerberos option %d\r\n", data[-1]);
	return;
    }
}
Ejemplo n.º 11
0
void
kerberos4_is(Authenticator *ap, unsigned char *data, int cnt)
{
    struct sockaddr_in addr;
    char realm[REALM_SZ];
    char instance[INST_SZ];
    int r;
    int addr_len;

    if (cnt-- < 1)
	return;
    switch (*data++) {
    case KRB_AUTH:
	if (krb_get_lrealm(realm, 1) != KSUCCESS) {
	    Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("No local realm\r\n");
	    return;
	}
	memmove(auth.dat, data, auth.length = cnt);
	if (auth_debug_mode) {
	    printf("Got %d bytes of authentication data\r\n", cnt);
	    printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
	    printd(auth.dat, auth.length);
	    printf("\r\n");
	}
	k_getsockinst(0, instance, sizeof(instance));
	addr_len = sizeof(addr);
	if(getpeername(0, (struct sockaddr *)&addr, &addr_len) < 0) {
	    if(auth_debug_mode)
		printf("getpeername failed\r\n");
	    Data(ap, KRB_REJECT, "getpeername failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    return;
	}
	r = krb_rd_req(&auth, KRB_SERVICE_NAME,
		       instance, addr.sin_addr.s_addr, &adat, "");
	if (r) {
	    if (auth_debug_mode)
		printf("Kerberos failed him as %s\r\n", name);
	    Data(ap, KRB_REJECT, (void *)krb_get_err_text(r), -1);
	    auth_finished(ap, AUTH_REJECT);
	    return;
	}
	/* save the session key */
	memmove(session_key, adat.session, sizeof(adat.session));
	krb_kntoln(&adat, name);

	if (UserNameRequested && !kuserok(&adat, UserNameRequested)){
	    char ts[MAXPATHLEN];
	    struct passwd *pw = getpwnam(UserNameRequested);

	    if(pw){
		snprintf(ts, sizeof(ts),
			 "%s%u",
			 TKT_ROOT,
			 (unsigned)pw->pw_uid);
		setenv("KRBTKFILE", ts, 1);
	    }
	    Data(ap, KRB_ACCEPT, NULL, 0);
	} else {
	    char *msg;

	    asprintf (&msg, "user `%s' is not authorized to "
		      "login as `%s'", 
		      krb_unparse_name_long(adat.pname, 
					    adat.pinst, 
					    adat.prealm), 
		      UserNameRequested ? UserNameRequested : "<nobody>");
	    if (msg == NULL)
		Data(ap, KRB_REJECT, NULL, 0);
	    else {
		Data(ap, KRB_REJECT, (void *)msg, -1);
		free(msg);
	    }
	}
	auth_finished(ap, AUTH_USER);
	break;
	
    case KRB_CHALLENGE:
#ifndef ENCRYPTION
	Data(ap, KRB_RESPONSE, NULL, 0);
#else
	if(!VALIDKEY(session_key)){
	    Data(ap, KRB_RESPONSE, NULL, 0);
	    break;
	}
	des_key_sched(&session_key, sched);
	{
	    des_cblock d_block;
	    int i;
	    Session_Key skey;

	    memmove(d_block, data, sizeof(d_block));

	    /* make a session key for encryption */
	    des_ecb_encrypt(&d_block, &session_key, sched, 1);
	    skey.type=SK_DES;
	    skey.length=8;
	    skey.data=session_key;
	    encrypt_session_key(&skey, 1);

	    /* decrypt challenge, add one and encrypt it */
	    des_ecb_encrypt(&d_block, &challenge, sched, 0);
	    for (i = 7; i >= 0; i--)
		if(++challenge[i] != 0)
		    break;
	    des_ecb_encrypt(&challenge, &challenge, sched, 1);
	    Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge));
	}
#endif
	break;

    case KRB_FORWARD:
	{
	    des_key_schedule ks;
	    unsigned char netcred[sizeof(CREDENTIALS)];
	    CREDENTIALS cred;
	    int ret;
	    if(cnt > sizeof(cred))
		abort();

	    des_set_key(&session_key, ks);
	    des_pcbc_encrypt((void*)data, (void*)netcred, cnt, 
			     ks, &session_key, DES_DECRYPT);
	    unpack_cred(netcred, cnt, &cred);
	    {
		if(strcmp(cred.service, KRB_TICKET_GRANTING_TICKET) ||
		   strncmp(cred.instance, cred.realm, sizeof(cred.instance)) ||
		   cred.lifetime < 0 || cred.lifetime > 255 ||
		   cred.kvno < 0 || cred.kvno > 255 ||
		   cred.issue_date < 0 || 
		   cred.issue_date > time(0) + CLOCK_SKEW ||
		   strncmp(cred.pname, adat.pname, sizeof(cred.pname)) ||
		   strncmp(cred.pinst, adat.pinst, sizeof(cred.pname))){
		    Data(ap, KRB_FORWARD_REJECT, "Bad credentials", -1);
		}else{
		    if((ret = tf_setup(&cred,
				       cred.pname,
				       cred.pinst)) == KSUCCESS){
		        struct passwd *pw = getpwnam(UserNameRequested);

			if (pw)
			  chown(tkt_string(), pw->pw_uid, pw->pw_gid);
			Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
		    } else{
			Data(ap, KRB_FORWARD_REJECT, 
			     krb_get_err_text(ret), -1);
		    }
		}
	    }
	    memset(data, 0, cnt);
	    memset(ks, 0, sizeof(ks));
	    memset(&cred, 0, sizeof(cred));
	}
	
	break;

    default:
	if (auth_debug_mode)
	    printf("Unknown Kerberos option %d\r\n", data[-1]);
	Data(ap, KRB_REJECT, 0, 0);
	break;
    }
}
Ejemplo n.º 12
0
int
kerberos5_is_auth (TN_Authenticator * ap, unsigned char *data, int cnt,
		   char *errbuf, int errbuflen)
{
  int r = 0;
  krb5_keytab keytabid = 0;
  krb5_authenticator *authenticator;
  char *name;
  krb5_data outbuf;
  krb5_keyblock *newkey = NULL;
  krb5_principal server;

# ifdef ENCRYPTION
  Session_Key skey;
# endif

  auth.data = (char *) data;
  auth.length = cnt;

  if (!r && !auth_context)
    r = krb5_auth_con_init (telnet_context, &auth_context);
  if (!r)
    {
      krb5_rcache rcache;

      r = krb5_auth_con_getrcache (telnet_context, auth_context, &rcache);
      if (!r && !rcache)
	{
	  r = krb5_sname_to_principal (telnet_context, 0, 0,
				       KRB5_NT_SRV_HST, &server);
	  if (!r)
	    {
	      r = krb5_get_server_rcache (telnet_context,
					  krb5_princ_component
					  (telnet_context, server, 0),
					  &rcache);
	      krb5_free_principal (telnet_context, server);
	    }
	}
      if (!r)
	r = krb5_auth_con_setrcache (telnet_context, auth_context, rcache);
    }

  if (!r && telnet_srvtab)
    r = krb5_kt_resolve (telnet_context, telnet_srvtab, &keytabid);
  if (!r)
    r = krb5_rd_req (telnet_context, &auth_context, &auth,
		     NULL, keytabid, NULL, &ticket);
  if (r)
    {
      snprintf (errbuf, errbuflen, "krb5_rd_req failed: %s",
		error_message (r));
      return r;
    }

  /* 256 bytes should be much larger than any reasonable
     first component of a service name especially since
     the default is of length 4. */
  if (krb5_princ_component (telnet_context, ticket->server, 0)->length < 256)
    {
      char princ[256];
      strncpy (princ,
	       krb5_princ_component (telnet_context, ticket->server, 0)->data,
	       krb5_princ_component (telnet_context, ticket->server,
				     0)->length);
      princ[krb5_princ_component (telnet_context, ticket->server, 0)->
	    length] = '\0';
      if (strcmp ("host", princ))
	{
	  snprintf (errbuf, errbuflen,
		    "incorrect service name: \"%s\" != \"host\"", princ);
	  return 1;
	}
    }
  else
    {
      strncpy (errbuf, "service name too long", errbuflen);
      return 1;
    }

  r = krb5_auth_con_getauthenticator (telnet_context,
				      auth_context, &authenticator);
  if (r)
    {
      snprintf (errbuf, errbuflen,
		"krb5_auth_con_getauthenticator failed: %s",
		error_message (r));
      return 1;
    }

# ifdef AUTH_ENCRYPT_MASK
  if ((ap->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON
      && !authenticator->checksum)
    {
      snprintf (errbuf, errbuflen,
		"authenticator is missing required checksum");
      return 1;
    }
# endif

  if (authenticator->checksum)
    {
      char type_check[2];
      krb5_checksum *cksum = authenticator->checksum;
      krb5_keyblock *key;

      type_check[0] = ap->type;
      type_check[1] = ap->way;

      r = krb5_auth_con_getkey (telnet_context, auth_context, &key);
      if (r)
	{
	  snprintf (errbuf, errbuflen,
		    "krb5_auth_con_getkey failed: %s", error_message (r));
	  return 1;
	}

      r = krb5_verify_checksum (telnet_context,
				cksum->checksum_type, cksum,
				&type_check, 2, key->contents, key->length);

      if (r)
	{
	  snprintf (errbuf, errbuflen,
		    "checksum verification failed: %s", error_message (r));
	  return 1;
	}
      krb5_free_keyblock (telnet_context, key);
    }

  krb5_free_authenticator (telnet_context, authenticator);
  if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
    {
      if ((r = krb5_mk_rep (telnet_context, auth_context, &outbuf)))
	{
	  snprintf (errbuf, errbuflen, "Make reply failed: %s",
		    error_message (r));
	  return 1;
	}

      Data (ap, KRB_RESPONSE, outbuf.data, outbuf.length);
    }

  if (krb5_unparse_name (telnet_context, ticket->enc_part2->client, &name))
    name = 0;

  Data (ap, KRB_ACCEPT, name, name ? -1 : 0);
  DEBUG (("telnetd: Kerberos5 identifies him as ``%s''\r\n",
	  name ? name : ""));
  auth_finished (ap, AUTH_USER);

  free (name);
  krb5_auth_con_getremotesubkey (telnet_context, auth_context, &newkey);

  if (session_key)
    {
      krb5_free_keyblock (telnet_context, session_key);
      session_key = 0;
    }

  if (newkey)
    {
      krb5_copy_keyblock (telnet_context, newkey, &session_key);
      krb5_free_keyblock (telnet_context, newkey);
    }
  else
    {
      krb5_copy_keyblock (telnet_context, ticket->enc_part2->session,
			  &session_key);
    }
  telnet_encrypt_key (&skey);
  return 0;
}
Ejemplo n.º 13
0
void
kerberos5_reply (TN_Authenticator * ap, unsigned char *data, int cnt)
{
# ifdef ENCRYPTION
  Session_Key skey;
# endif
  static int mutual_complete = 0;

  if (cnt-- < 1)
    return;

  switch (*data++)
    {
    case KRB_REJECT:
      if (cnt > 0)
	printf ("[ Kerberos V5 refuses authentication because %.*s ]\r\n",
		cnt, data);
      else
	printf ("[ Kerberos V5 refuses authentication ]\r\n");
      auth_send_retry ();
      return;

    case KRB_ACCEPT:
      if (!mutual_complete)
	{
	  if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
	    {
	      printf
		("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n");
	      auth_send_retry ();
	      break;
	    }
	  telnet_encrypt_key (&skey);
	}

      if (cnt)
	printf ("[ Kerberos V5 accepts you as ``%.*s''%s ]\r\n", cnt, data,
		mutual_complete ?
		" (server authenticated)" : " (server NOT authenticated)");
      else
	printf ("[ Kerberos V5 accepts you ]\r\n");
      auth_finished (ap, AUTH_USER);
# ifdef  FORWARD
      if (forward_flags & OPTS_FORWARD_CREDS)
	kerberos5_forward (ap);
# endif
      break;

    case KRB_RESPONSE:
      if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
	{
	  krb5_ap_rep_enc_part *reply;
	  krb5_data inbuf;
	  krb5_error_code r;

	  inbuf.length = cnt;
	  inbuf.data = (char *) data;

	  if ((r = krb5_rd_rep (telnet_context, auth_context, &inbuf,
				&reply)))
	    {
	      printf ("[ Mutual authentication failed: %s ]\r\n",
		      error_message (r));
	      auth_send_retry ();
	      break;
	    }

	  krb5_free_ap_rep_enc_part (telnet_context, reply);
	  telnet_encrypt_key (&skey);
	  mutual_complete = 1;
	}
      break;

# ifdef  FORWARD
    case KRB_FORWARD_ACCEPT:
      printf ("[ Kerberos V5 accepted forwarded credentials ]\r\n");
      break;

    case KRB_FORWARD_REJECT:
      printf
	("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n",
	 cnt, data);
      break;
# endif	/* FORWARD */

    default:
      DEBUG (("Unknown Kerberos option %d\r\n", data[-1]));
    }
}
Ejemplo n.º 14
0
static RETSIGTYPE
auth_intr (int sig ARG_UNUSED)
{
  auth_finished (0, AUTH_REJECT);
}