LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Other *NIX Forums > *BSD
User Name
Password
*BSD This forum is for the discussion of all BSD variants.
FreeBSD, OpenBSD, NetBSD, etc.

Notices


Reply
  Search this Thread
Old 06-07-2013, 09:25 AM   #1
methodtwo
Member
 
Registered: May 2007
Posts: 146

Rep: Reputation: 18
Need help with C code(BSD-Based rlogind.c)


Hi
I have a few quesitons regarding a version of rlogind.c that i'm hacking on. I'm not crazy enough to think that anyone will use it or distribute it, i'm just doing it as a programming exercise. I use a variation of rlogin.c, for the client, from the one in the original w.rich stevens network prog book.
The server program has a function to multiplex between the network and master-side of the pseudo terminal.This is after a function has been called which opens the master and slave of the pseudo terminal and exec()s /bin/login like so:
Code:
if(excel("/bin/login", "login", "-p", "-h", hp->h_name, "-f", user_name, (char *)0)== -1)
   perror("/bin/login error");
Before the exec() of /bin/login the slave side is opened after a fork() and a setsid() to put what ever is exec()'d after this fork() in it's own session. Then the slave-side becomes the CTTY of anything executed in this child. Also dup2 is then called to set the stdin, stout, stderr to the slave's file descriptor(returned from open()ing the slave-side, as explained above). Thus, i thought, /bin/login would have it's stdin, stout and std err connected to the slave-side of the pseudo term(?). Is this wrong? What would stop this being the case? What would stop the output from /bin/login from ending up at the master-side of the tty and thus be output on the socket(to be sent to the client)? Or is it most likely to be the multiplexing of socket/master-side I/O that is wrong? Here is the code that does this multiplexing(of socket and master-side I/O....a tiny bit of it is from the BSD version of rlogind.c):
Code:
        /*
 * Copyright (c) 1983 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
          max_pfd = max(p_ptr.connfd, p_ptr.fdm);
        FD_ZERO(&errorset);
        FD_SET(p_ptr.fdm, &errorset);
        FD_ZERO(&p_error);
        FD_SET(p_ptr.fdm, &p_error);

       	if ((child = fork()) < 0) {
		perror("fork error");
	} else if (child == 0) {	/* child copies stdin to ptym */
		for ( ; ; ) {
                   errset = errorset;
                   select(maxfd + 1, NULL, NULL, &errset, NULL);
                   
                    if(FD_ISSET(p_ptr.fdm, &errset)) {
                        cc = read(p_ptr.fdm, &cntlbyte, 1);
                        if(cc == 1 && pkcontrol(cntlbyte)){
				cntlbyte |= oobdata[0];
		               send(p_ptr.connfd, &cntlbyte, 1, MSG_OOB);
                                if(cntlbyte & TIOCPKT_FLUSHWRITE) 
				   	memset(buf, 0, sizeof(buf));
                        }
                   }
	
		if ((nread = read(p_ptr.connfd, buf, BUFFSIZE)) < 0)
				perror("read error from socket");
			else if (nread == 0)
				break;
              
			for(ptr = buf; ptr < buf+nread-1; ptr++) {
				if(ptr[0] == magic[0] &&
				   ptr[1] == magic[1]) {
				   left = nread - (ptr - buf);	
                                   n = control(p_ptr.fdm, ptr, left);
				   if(n) {
					left -= n;
                                        if(left > 0)
					  bcopy(ptr+n, ptr, left);
					nread -= n;
				   }
				}
			}
		 
		if (writen(p_ptr.fdm, buf, nread) != nread)
			perror("writen error to master pty");
		   
                }/*End of for? */
                   
                
		/*
		 * We always terminate when we encounter an EOF on stdin,
		 * but we notify the parent only if ignoreeof is 0.
		 */
		if (p_ptr.ignoreeof == 0)
			kill(getppid(), SIGTERM);	/* notify parent */
		exit(0);	/* and terminate; child can't return */

       }/*end of child */

	/*
	 * Parent copies ptym to stdout.
	 */
	if (signal(SIGTERM, sig_term) == SIG_ERR)
		perror("signal_intr error for SIGTERM");

	for ( ; ; ) {
                p_err = p_error;
                /*p_wset = p_write;
                p_rset = p_read;*/

                select(max_pfd + 1, NULL, NULL, &p_err, NULL);

                if(FD_ISSET(p_ptr.fdm, &p_err)) {
                   cc = read(p_ptr.fdm, &cntlbyte, 1);

                   if(cc == 1 && pkcontrol(cntlbyte)){
                     cntlbyte |= oobdata[0];
                     send(p_ptr.fdm, &cntlbyte, 1, MSG_OOB);
                     if(cntlbyte & TIOCPKT_FLUSHWRITE)
                        memset(buf, 0, sizeof(buf));
                   }
                }
                
		  if ((nread = read(p_ptr.fdm, buffer, BUFFSIZE)) <= 0){
                        perror("Read error on pty master");
			break; /* signal caught, error, or EOF */
                  /*if(buffer[0] == 0) {*/
                   }
                  if(pkcontrol(buffer[0])) {
			   buffer[0] |= oobdata[0];
			   send(p_ptr.connfd, &buffer[0], 1, MSG_OOB);
                       
                     }else {  
                     if (writen(p_ptr.connfd, buffer, nread) != nread)
		  	  perror("writen error to stdout");
                  
                 }/*else*/
                } /*Closes for? */                 
             

	/*
	 * There are three ways to get here: sig_term() below caught the
	 * SIGTERM from the child, we read an EOF on the pty master (which
	 * means we have to signal the child to stop), or an error.
	 */
     
	if (sigcaught == 0)	/* tell child if it didn't send us the signal */
		kill(child, SIGTERM);
	/*
	 * Parent returns to caller.
	 */
   /* Need to close connection and do any clean up here
    *
    */
   
   close(p_ptr.connfd);
   }
   return(0);
}
I've looked at /etc/login.access i even removed the user i was trying to log in as from wheel! I was hoping that with the pseudo term and network set up(the network functions are executing without (p)errors) that /bin/login would just execute the login shell in the same environment( as you can see i used the "-p" flag to /bin/login! Then when /bin/login exec()'d /usr/local/bin/bash that the code above would pass the output from bash to the slave-side, which would appear at the master-side(since the slave is in raw-mode). As the slave was put in raw-mode anything output to it would appear as output for the socket and visa-versa(Although the master-side in the server isn't set to raw). Is that the right way to do it? When i run the server on FreeBSD no errors are output. When the client is run on os x there is a read error on the client function called reader()(from the rlogin client in rich stevens' net prog book).
So do i have to edit /etc/ttys and put "secure" for evert ttyXY? I ran tcpdump and the only packets exchanged were the client sending the user name and the server successfully reading this and sending back an "o.k". What are the "gotchas" for /bin/login and pseudo terms talking to the network? Why might the login fail? I've tried exec()ing /bin/login with and without the "-f" flag. When i did use the "-f" flag i tried logging in as the user who was already logged in and with a user who was not already logged in! I don't know why i can't get this to work(?)
I can post the whole code of the server and/or the client if necessary. But that is kinda crazy(as is wanting to code such an application as rlogind!)
Any help/suggestions would be gratefully received
Thank you very much in advance.

Last edited by methodtwo; 06-08-2013 at 03:31 PM. Reason: Have changed the code
 
Old 06-07-2013, 09:27 AM   #2
methodtwo
Member
 
Registered: May 2007
Posts: 146

Original Poster
Rep: Reputation: 18
Should this post be moved to the programming section? I posted it here because while it is UNIX programming it only runs on FreeBSD and OS X at the moment!
Also the firewall is off on the server when i test the code. The client doesn't use rcmd to send the login credentials. It just write()s the username to the socket. The username is then used when /bin/login is exec()'d(as show above)
cheers

Last edited by methodtwo; 06-07-2013 at 11:52 AM.
 
1 members found this post helpful.
Old 07-04-2013, 01:42 AM   #3
methodtwo
Member
 
Registered: May 2007
Posts: 146

Original Poster
Rep: Reputation: 18
I found a solution but since no one in is interested( quite rightly so probably!) then i'll just say that it was solved.
 
Old 07-13-2013, 04:18 AM   #4
kooru
Senior Member
 
Registered: Sep 2012
Posts: 1,385

Rep: Reputation: 275Reputation: 275Reputation: 275
Hi methodtwo
Maybe now nobody have interest for your problem, but in the future someone could need about your solutions.

So if you want/can, please post the solutions.
 
Old 07-18-2013, 03:34 PM   #5
methodtwo
Member
 
Registered: May 2007
Posts: 146

Original Poster
Rep: Reputation: 18
Hi
ERm o.k then. The loop to multiplex the i/o from/to the socket/terminal was the one below. It was just an experiment to see if i could implement something that was as nice as the select(2) loop in the BSD version. The answer to that was no as it turned out. However it works! The other bit of the solution was calling the function that this loop is a part of after fork()ing the child to exec() /bin/login(rather than returning from the parent of this exec("/bin/login", etc, etc) child. Thus the child didn't die and so the remote shell stayed up. Sorry that's a really bad explanation but no one cares(quite rightly so!).
Code:
rcvstate = READING;

    if(child_pid == 0){
      for(;;){
        if(rcvstate == READING)
       	       if((pcc = read(fdm, pibuf, sizeof(pibuf))) < 0)
                   continue;
               
          if(pcc > 1){
               rcvstate = WRITING;
	       pbp = pibuf;
          }
        
        if(pcc == 0)
              break;
       	else if (pcc == 1 && pkcontrol(pibuf[0])) {
		pibuf[0] |= oobdata[0];
		(void)send(connfd, &pibuf[0], 1, MSG_OOB);
		if (pibuf[0] & TIOCPKT_FLUSHWRITE)
			pcc = 0;
		}
        else if (pcc > 1 && pibuf[0] == 0 
                 && rcvstate == WRITING){
               pbp++;

                while((rem = pcc - (pbp - pibuf)) > 0){
                if((n = write(connfd, pbp, rem)) < 0){
                    sleep(1);
	            continue;
                }
                if(n == 0)
                    break;
		pbp += n;
        }
        if(rem == 0)
           rcvstate = READING;
        if(n ==0)
           break; 
       
                   
       } else {
               if (pkcontrol(pibuf[0])) {
		pibuf[0] |= oobdata[0];
		(void)send(connfd, &pibuf[0], 1 , MSG_OOB);
         }
         pcc = 0;
     }
     
  } /* End of for.... */
 if(ignoreeof == 0)
    kill(getppid(), SIGTERM);
 exit(0);
}/* End of child */

/* Parent........*/
   
   if(signal(SIGTERM, sig_term) == SIG_ERR)
	perror("signal handler for protocol parent!");
   rcvstate = READING;
        for(;;){

          if(rcvstate == READING){
             if((fcc = read(connfd, fibuf, sizeof(fibuf))) < 0)
                  continue;
          if(fcc == 0)
             break;
          if(fcc > 0){
            cc = fcc;
            rcvstate = WRITING;
          }
       }
          if(fcc > 0 && rcvstate == WRITING){
            fbp = fibuf;
          if(fibuf[0] == magic[0] &&
                  fibuf[1] == magic[1]) {
        top:
            for(cp = fibuf; cp < fibuf+fcc-1; cp++)
               if(cp[0] == magic[0] &&
                  cp[1] == magic[1]) {
                    remaining = fcc - (cp-fibuf);
                    n = control(fdm, cp, remaining);
                    if(n){
                         remaining -= n;
			 if(remaining > 0)
				bcopy(cp+n, cp, remaining);
                         fcc -= n;
                         goto top; /* Ugly eh? ;process another `in-band' magic cookie!...*/
		    }
              }
             rcvstate = READING;
           }
           else{
             while(( rem = cc - (fbp - fibuf)) > 0){
		if((n = write(fdm, fbp, rem)) < 0)
                   continue;
	        if(n == 0)
		   break;
                fbp += n;
       
           }
         if(n == 0)
		break;
         if(rem == 0)
                rcvstate = READING;
         }
        }
    }
    if(sigcaught == 0)
      kill(child_pid, SIGTERM);

    /* Return to caller....*/         
  
}

}
 
2 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How to filter the linux kernel code based on config file. removing unnecessary code atulmt Linux - Kernel 4 06-29-2013 11:14 PM
Is there any benefit to rewrite OSS-based code to ALSA-based code? RogueWarrior65 Linux - Software 1 08-13-2010 02:11 AM
rsh problem - PAM authentication failed for in.rlogind davey123 Linux - Security 0 12-05-2005 11:24 AM
Is Mac based on BSD ? inspiredbymetal Other *NIX 6 10-17-2005 04:55 PM
*BSD based Live CD danny_beta_read Linux - Distributions 2 04-10-2004 11:37 PM

LinuxQuestions.org > Forums > Other *NIX Forums > *BSD

All times are GMT -5. The time now is 02:59 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration