Esempio n. 1
0
int do_krb5_comm(krb5_context context, krb5_keytab keytab, krb5_principal server, char *cmddir) {
	struct sockaddr_in c_saddr, s_saddr;
	socklen_t namelen;
	int sock = 0;
	int len;
	char buff[BUFFSIZE];
	char *cname = NULL;
	krb5_error_code retval;
	krb5_data kdata, message;
	krb5_auth_context auth_context = NULL;
	krb5_ticket *ticket;
	krb5_address ckaddr, skaddr;
	krb5_rcache rcache;
	krb5_data rcache_name;
	long srand, rrand;
	int fd[2];
	char rcname_piece[RC_PIECE_MAXLEN];

	namelen = sizeof(c_saddr);
	if (getpeername(sock, (struct sockaddr *)&c_saddr, &namelen) < 0) {
		syslog(LOG_ERR, "getpeername: %m");
		return 1;
	}

	namelen = sizeof(s_saddr);
	if (getsockname(sock, (struct sockaddr *)&s_saddr, &namelen) < 0) {
		syslog(LOG_ERR, "getsockname: %m");
		return 1;
	}

	/* INIT MSG = random number */
	srand = random();

	/* Send it */
	if (send(sock, &srand, sizeof(srand), 0) < 0) {
		syslog(LOG_ERR, "%m while sending init message");
		return 1;
	}
	if (recv(sock, &rrand, sizeof(rrand), 0) < 0) {
		syslog(LOG_ERR, "%m while receiving init reply");
		return 1;
	}

	/* Reply should contain the same message (number) */
	if (srand != rrand) {
		syslog(LOG_ERR, "Bad init reply");
		return 1;
	}

	/* Do authentication */
	if (retval = krb5_recvauth(context, &auth_context, (krb5_pointer)&sock, AFSADM_VERSION, server, 0, keytab, &ticket)) {
		syslog(LOG_ERR, "recvauth failed: %s", error_message(retval));
		exit(1);
	}

	/* Get client name */
	if (retval = krb5_unparse_name(context, ticket->enc_part2->client, &cname)) {
		syslog(LOG_ERR, "unparse failed: %s", error_message(retval));
		return 1;
	}

	if (ticket)
		krb5_free_ticket(context, ticket);

	if (debug)
		syslog(LOG_DEBUG, "Principal %s", cname);

	/*******************************************************************/

	ckaddr.addrtype = ADDRTYPE_IPPORT;
	ckaddr.length   = sizeof(c_saddr.sin_port);
	ckaddr.contents = (krb5_octet *)&c_saddr.sin_port;

	skaddr.addrtype = ADDRTYPE_IPPORT;
	skaddr.length   = sizeof(s_saddr.sin_port);
	skaddr.contents = (krb5_octet *)&s_saddr.sin_port;
	if ((retval = krb5_auth_con_setports(context, auth_context, &skaddr, &ckaddr))) {
		syslog(LOG_ERR, "%s while setting ports", error_message(retval));
		return 1;
	}

	/* Set foreign_addr for rd_priv() */
	ckaddr.addrtype = ADDRTYPE_INET;
	ckaddr.length   = sizeof(c_saddr.sin_addr);
	ckaddr.contents = (krb5_octet *)&c_saddr.sin_addr;

	/* Set local_addr  */
	skaddr.addrtype = ADDRTYPE_INET;
	skaddr.length   = sizeof(s_saddr.sin_addr);
	skaddr.contents = (krb5_octet *)&s_saddr.sin_addr;

	if ((retval = krb5_auth_con_setaddrs(context, auth_context, &skaddr, &ckaddr))) {
		syslog(LOG_ERR, "%s while setting addrs", error_message(retval));
		return 1;
	}

	/* Receive a request */
	if ((len = recv(sock, (char *)buff, sizeof(buff), 0)) < 0) {
		syslog(LOG_ERR, "%m while receiving datagram");
		return 1;
	}

	kdata.length = len;
	kdata.data = buff;

	if (debug)
		syslog(LOG_DEBUG, "Received %d bytes", len);

	/* Decrypt it */
	if ((retval = krb5_rd_priv(context, auth_context, &kdata, &message, NULL))) {
		syslog(LOG_ERR, "%s while verifying PRIV message", error_message(retval));
		return 1;
	}

	if (message.length > 0) {
#ifdef __osf__
		sprintf(rcname_piece, "afsadmd_%d",  getpid());
#else
		snprintf(rcname_piece, RC_PIECE_MAXLEN, "afsadmd_%d", getpid());
#endif
		rcache_name.data = rcname_piece;
		rcache_name.length = strlen(rcache_name.data);

		if ((retval = krb5_get_server_rcache(context, &rcache_name, &rcache))) {
			syslog(LOG_ERR, "%s while getting server rcache", error_message(retval));
			return 1;
		}

		/* set auth_context rcache */
		if (retval = krb5_auth_con_setrcache(context, auth_context, rcache)) {
			syslog(LOG_ERR, "%s while setting rcache", error_message(retval));
			return 1;
		}

		/*********************************************************************
		 * Call the desired command, read stdout/stderr, send it
		 *********************************************************************/

		/* create fork */
		if (pipe(fd) == -1)
			printf("Failed create fork with pipe().\n");

		if (fork() == 0) {
			close(fd[0]);
			close(1);
			close(2);
			dup2(fd[1], 1);
			dup2(fd[1], 2);

			/* Call required command */
			do_command(context, keytab, server, cname, message.data, cmddir );
			krb5_xfree(message.data);
			exit(0);
		} else {
			/* Read stdout/stderr from pipe, store it to the buffer, encrypt it a send to the client */
			krb5_data message, kdata;
			char buff[PIPEBUFF];
			int n = 0;
			int len = 0;
			int sent = 0;
			int counter = 0;
			int end = 0;
			short netlen;
			time_t starttime, oldtime, newtime;
			FILE *pipedes;

			close(fd[1]);
			pipedes = fdopen(fd[0], "r");

			starttime = oldtime = time(NULL);

			for (n = 0; end == 0; ) {
				/* Read line from pipe */
				if (fgets(buff + n, PIPEBUFF - n, pipedes) == NULL)
					end++;
				else
					n = strlen(buff);

				/* Get time */
				newtime = time(NULL);

				/* Send buffer when
				 *    a) buffer is full
				 *    b) buffer contains data and
				 *      1) end-of-file encountered (end flag)
				 *      2) buffer sent before 1s
				 */
				if ((n == PIPEBUFF) || (((newtime > oldtime) || end ) && (n != 0))) {
					/* Prepare data for sending */
					message.data = buff;
					message.length = n;
					kdata.data = NULL;

					/* Make the encrypted message */
					if ((retval = krb5_mk_priv(context, auth_context, &message, &kdata, NULL))) {
						syslog(LOG_ERR, "%s while making KRB_PRIV message", error_message(retval));
						return 1;
					}

					/* Convert byte order */
					netlen = htons((short)kdata.length);

					/* Send len of encrypted data */
					if ((len = send(sock, (char *)&netlen, sizeof(netlen), 0)) != sizeof(netlen)) {
						krb5_xfree(kdata.data);
						syslog(LOG_ERR, "%m while sending len of PRIV message");
						return 1;
					}

					/* Send it */
					if ((len = send(sock, (char *)kdata.data, kdata.length, 0)) != kdata.length) {
						syslog(LOG_ERR, "%m while sending PRIV message");
						krb5_xfree(kdata.data);
						return 1;
					}

					/* Statistics */
					sent += len;
					counter++;

					/* Timestanmp */
					oldtime = newtime;
					n = 0;

					krb5_xfree(kdata.data);
				}
			}

			newtime = time(NULL);

			if (debug)
				syslog(LOG_DEBUG, "Sent %d bytes in %ds [%d fragment(s)]", sent, (int)(newtime - starttime),  counter);
		}
	}

	//FIXME: There is no way to close or destroy rcache declared in krb5 headers
	//krb5_rc_destroy(context, rcache);

	/* set auth_context rcache */
	if (retval = krb5_auth_con_setrcache(context, auth_context, rcache)) {
		syslog(LOG_ERR, "%s while setting rcache to NULL", error_message(retval));
		return 1;
	}

	free(cname);
	krb5_auth_con_free(context, auth_context);
	return 0;
}
Esempio n. 2
0
/* 
 * Serialize krb5_auth_context.
 */
static krb5_error_code
ser_acontext_test(krb5_context kcontext, int verbose)
{
    krb5_error_code	kret;
    krb5_auth_context	actx;
    krb5_address	local_address;
    krb5_address	remote_address;
    krb5_octet		laddr_bytes[16];
    krb5_octet		raddr_bytes[16];
    krb5_keyblock	ukeyblock;
    krb5_octet		keydata[8];
    krb5_authenticator	aent;
    char		clname[128];
    krb5_authdata	*adatalist[3];
    krb5_authdata	adataent;

    actx = (krb5_auth_context) NULL;
    if (!(kret = krb5_auth_con_init(kcontext, &actx)) &&
	!(kret = ser_data(verbose, "> Vanilla auth context",
			  (krb5_pointer) actx,
			  KV5M_AUTH_CONTEXT))) {
	memset(&local_address, 0, sizeof(local_address));
	memset(&remote_address, 0, sizeof(remote_address));
	memset(laddr_bytes, 0, sizeof(laddr_bytes));
	memset(raddr_bytes, 0, sizeof(raddr_bytes));
	local_address.addrtype = ADDRTYPE_INET;
	local_address.length = sizeof(laddr_bytes);
	local_address.contents = laddr_bytes;
	laddr_bytes[0] = 6;
	laddr_bytes[1] = 2;
	laddr_bytes[2] = 69;
	laddr_bytes[3] = 16;
	laddr_bytes[4] = 1;
	laddr_bytes[5] = 0;
	laddr_bytes[6] = 0;
	laddr_bytes[7] = 127;
	remote_address.addrtype = ADDRTYPE_INET;
	remote_address.length = sizeof(raddr_bytes);
	remote_address.contents = raddr_bytes;
	raddr_bytes[0] = 6;
	raddr_bytes[1] = 2;
	raddr_bytes[2] = 70;
	raddr_bytes[3] = 16;
	raddr_bytes[4] = 1;
	raddr_bytes[5] = 0;
	raddr_bytes[6] = 0;
	raddr_bytes[7] = 127;
	if (!(kret = krb5_auth_con_setaddrs(kcontext, actx,
					    &local_address,
					    &remote_address)) &&
	    !(kret = krb5_auth_con_setports(kcontext, actx,
					    &local_address,
					    &remote_address)) &&
	    !(kret = ser_data(verbose, "> Auth context with addrs/ports", 
			      (krb5_pointer) actx,
			      KV5M_AUTH_CONTEXT))) {
	    memset(&ukeyblock, 0, sizeof(ukeyblock));
	    memset(keydata, 0, sizeof(keydata));
	    ukeyblock.enctype = ENCTYPE_DES_CBC_MD5;
	    ukeyblock.length = sizeof(keydata);
	    ukeyblock.contents = keydata;
	    keydata[0] = 0xde;
	    keydata[1] = 0xad;
	    keydata[2] = 0xbe;
	    keydata[3] = 0xef;
	    keydata[4] = 0xfe;
	    keydata[5] = 0xed;
	    keydata[6] = 0xf0;
	    keydata[7] = 0xd;
	    if (!(kret = krb5_auth_con_setuseruserkey(kcontext, actx,
						      &ukeyblock)) &&
		!(kret = ser_data(verbose, "> Auth context with user key",
				  (krb5_pointer) actx,
				  KV5M_AUTH_CONTEXT)) &&
		!(kret = krb5_auth_con_initivector(kcontext, actx)) &&
		!(kret = ser_data(verbose, "> Auth context with new vector",
				  (krb5_pointer) actx,
				  KV5M_AUTH_CONTEXT)) &&
		(krb5_xfree(actx->i_vector), actx->i_vector) &&
		!(kret = krb5_auth_con_setivector(kcontext, actx,
						  (krb5_pointer) print_erep)
		  ) &&
		!(kret = ser_data(verbose, "> Auth context with set vector",
				  (krb5_pointer) actx,
				  KV5M_AUTH_CONTEXT))) {
		/*
		 * Finally, add an authenticator.
		 */
		memset(&aent, 0, sizeof(aent));
		aent.magic = KV5M_AUTHENTICATOR;
		snprintf(clname, sizeof(clname),
			 "help/me/%[email protected]", (int) getpid());
		actx->authentp = &aent;
		if (!(kret = krb5_parse_name(kcontext, clname,
					     &aent.client)) &&
		    !(kret = ser_data(verbose,
				      "> Auth context with authenticator",
				      (krb5_pointer) actx,
				      KV5M_AUTH_CONTEXT))) {
		    adataent.magic = KV5M_AUTHDATA;
		    adataent.ad_type = 123;
		    adataent.length = 128;
		    adataent.contents = (krb5_octet *) stuff;
		    adatalist[0] = &adataent;
		    adatalist[1] = &adataent;
		    adatalist[2] = (krb5_authdata *) NULL;
		    aent.authorization_data = adatalist;
		    if (!(kret = ser_data(verbose,
					  "> Auth context with full auth",
					  (krb5_pointer) actx,
					  KV5M_AUTH_CONTEXT))) {
			if (verbose)
			    printf("* krb5_auth_context test succeeded\n");
		    }
		    krb5_free_principal(kcontext, aent.client);
		}
		actx->authentp = (krb5_authenticator *) NULL;
	    }
	}
    }
    if (actx)
	krb5_auth_con_free(kcontext, actx);
    if (kret)
	printf("* krb5_auth_context test failed\n");
    return(kret);
}
Esempio n. 3
0
/* XXX - check for cleanup */
krb5_error_code
setup_auth_context(krb5_context context,
		   krb5_auth_context auth_context,
		   struct sockaddr_in *localaddr,
		   struct sockaddr_in *remoteaddr,
		   char *uniq)
{
    krb5_address  	laddr, raddr, *portlocal_addr;
    krb5_rcache 	rcache;
    krb5_data		rcache_name;
    char       		*outaddr;
    krb5_error_code	retval;


#ifndef HEIMDAL
/* Setting ports isn't compatible with Heimdal, if this code
   is enabled, it's not possible to have an interoperable setup */
#if 0
    laddr.addrtype = ADDRTYPE_IPPORT;
    laddr.length = sizeof(localaddr->sin_port);
    laddr.contents = (krb5_octet *)&(localaddr->sin_port);

    raddr.addrtype = ADDRTYPE_IPPORT;
    raddr.length = sizeof(remoteaddr->sin_port);
    raddr.contents = (krb5_octet *)&(remoteaddr->sin_port);
    if (retval = krb5_auth_con_setports(context, auth_context,
					 &laddr, &raddr)) {
	sprintf(auth_con_error, "%s while setting auth_con ports\n",
		error_message(retval));
	return retval;
    }
#endif
#endif

#ifdef HEIMDAL
    laddr.addr_type = KRB5_ADDRESS_INET;
    laddr.address.length = sizeof(localaddr->sin_addr);
    laddr.address.data = (void *)&(localaddr->sin_addr);

    raddr.addr_type = KRB5_ADDRESS_INET;
    raddr.address.length = sizeof(remoteaddr->sin_addr);
    raddr.address.data = (void *)&(remoteaddr->sin_addr);
#else
    laddr.addrtype = ADDRTYPE_INET;
    laddr.length = sizeof(localaddr->sin_addr);
    laddr.contents = (krb5_octet *)&(localaddr->sin_addr);

    raddr.addrtype = ADDRTYPE_INET;
    raddr.length = sizeof(remoteaddr->sin_addr);
    raddr.contents = (krb5_octet *)&(remoteaddr->sin_addr);
#endif

    if (retval = krb5_auth_con_setaddrs(context, auth_context,
					 &laddr, &raddr)) {
	sprintf(auth_con_error, "%s while setting auth_con addresses\n",
		error_message(retval));
	return retval;
    }


#ifdef HEIMDAL
#else
    /* Set up replay cache */ 
    if ((retval = krb5_gen_portaddr(context,
				    &laddr,
				    (krb5_pointer) &(localaddr->sin_port),
				    &portlocal_addr))) {
	sprintf(auth_con_error, "%s while generating port address",
		error_message(retval));
	return retval;
    }
    
    if ((retval = krb5_gen_replay_name(context, portlocal_addr,
				       uniq, &outaddr))) {
	sprintf(auth_con_error, "%s while generating replay cache name",
		error_message(retval));
	return retval;
    }

    rcache_name.length = strlen(outaddr);
    rcache_name.data = outaddr;

    if ((retval = krb5_get_server_rcache(context, &rcache_name, &rcache))) {
	sprintf(auth_con_error, "%s while getting server rcache",
		error_message(retval));
	return retval;
    }

    if (retval = krb5_auth_con_setrcache(context, auth_context, rcache)) {
	sprintf(auth_con_error, "%s setting rcache",
		error_message(retval));
	return retval;
    }
#endif
	
    return retval;
}
Esempio n. 4
0
krb5_error_code KRB5_CALLCONV
krb5_auth_con_genaddrs(krb5_context context, krb5_auth_context auth_context, int infd, int flags)
{
    krb5_error_code       retval;
    krb5_address        * laddr;
    krb5_address        * lport;
    krb5_address        * raddr;
    krb5_address        * rport;
    SOCKET              fd = (SOCKET) infd;
    struct addrpair laddrs, raddrs;

#ifdef HAVE_NETINET_IN_H
    struct sockaddr_storage lsaddr, rsaddr;
    GETSOCKNAME_ARG3_TYPE ssize;

    ssize = sizeof(struct sockaddr_storage);
    if ((flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) ||
        (flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR)) {
        retval = getsockname(fd, ss2sa(&lsaddr), &ssize);
        if (retval)
            return retval;

        if (cvtaddr (&lsaddr, &laddrs)) {
            laddr = &laddrs.addr;
            if (flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR)
                lport = &laddrs.port;
            else
                lport = 0;
        } else
            return KRB5_PROG_ATYPE_NOSUPP;
    } else {
        laddr = NULL;
        lport = NULL;
    }

    ssize = sizeof(struct sockaddr_storage);
    if ((flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) ||
        (flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR)) {
        retval = getpeername(fd, ss2sa(&rsaddr), &ssize);
        if (retval)
            return errno;

        if (cvtaddr (&rsaddr, &raddrs)) {
            raddr = &raddrs.addr;
            if (flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)
                rport = &raddrs.port;
            else
                rport = 0;
        } else
            return KRB5_PROG_ATYPE_NOSUPP;
    } else {
        raddr = NULL;
        rport = NULL;
    }

    if (!(retval = krb5_auth_con_setaddrs(context, auth_context, laddr, raddr)))
        return (krb5_auth_con_setports(context, auth_context, lport, rport));
    return retval;
#else
    return KRB5_PROG_ATYPE_NOSUPP;
#endif
}