Code to check Password Server Group Memberships

Clay Jones clayljones at yahoo.com
Thu Mar 12 17:00:17 GMT 1998


I am not a member of the samba listserv, but I wanted to contribute
the following code to the samba effort.

The following is clipped from some experimental
changes I have made to my own copy of the samba 
source.  I have not included all of the changes 
because I don't have the time to.  But someone should 
be able to properly do the integration without too 
much effort.

Summary, these changes have allowed me to create 
shares and specify a list of domain groups to be a 
member of.  If the user is a member of at least one 
group, then I have used the "force user" option to set 
the uid for all file access.

This has given me the ability to provide a share to 
users without having to do any user maintenance on the 
Unix box.  All I have to do is add the user to the 
domain and they can access the share on samba.

It allows the samba server to be remotely administered 
via NT Domains

The needed changes include but may not be limited to:

    Passing the user name into server_validate

    Storing the list of groups away for validation at 
    share use time

    Parsing for and storing "Password Server Groups"
    per share

    Validating group membership at share use time
  

I hope someone finds this of use and adds it into the
real samba codebase.  

Does anyone know how to get a list of ALL domain 
groups, not just ones that the current user is a 
member of?  I have some packet traces showing a very 
complex way which involves opening pipes and allot of 
non intuitive packets.  I just haven't had the time to 
try to figure out how they work.  If someone knows the 
breakdown, I would try to code some other possibly 
nice features in.

Clay L Jones


/* Some bytes to be copied into the get grouplist request */
uchar gpipe[] =
{
    0x1A,          /* Unsure what this should be, I have seen 1A and
F0 */
    '\\', 0,
    'P',  0,
    'I',  0,
    'P',  0,
    'E',  0,
    '\\', 0,
    'L',  0,
    'A',  0,
    'N',  0,
    'M',  0,
    'A',  0,
    'N',  0,
     0,   0,
    0x3B, 0, 0x7A, 0x57, 0x72, 0x4C, 0x65,  /* no idea what these mean
*/
    0x68, 0, 0x42, 0x32, 0x31, 0
};


/****************************************************************************
attempted support for server level security 
****************************************************************************/
BOOL server_validate(char *buf, char *user)
{
  pstring inbuf,outbuf;  
  BOOL ret;

  if (password_client < 0) {
    DEBUG(1,("%s not connected\n",pserver));
    return(False);
  }  

  bzero(inbuf,sizeof(inbuf));
  memcpy(outbuf,buf,sizeof(outbuf));

  /* send a session setup command */
  CVAL(outbuf,smb_flg) = 0x8;
  SSVAL(outbuf,smb_flg2,0x1);
  CVAL(outbuf,smb_vwv0) = 0xFF;

  set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False);

  SCVAL(inbuf,smb_rcls,1);

  send_smb(password_client,outbuf);
  ret = receive_smb(password_client,inbuf,5000);

  if (!ret || CVAL(inbuf,smb_rcls) != 0) {
    DEBUG(1,("password server %s rejected the password\n",pserver));
    return(False);
  }

  /* if logged in as guest then reject */
  if ((SVAL(inbuf,smb_vwv2) & 1) != 0) {
    DEBUG(1,("password server %s gave us guest only\n",pserver));
    return(False);
  }


  /* Do we have a user  */
  if(user && *user)
  {
      int ulen;
      uchar *p;
      struct passwd *pw;
      char ato[40];

      /* As a part of password server groups we need to find what groups
       * this user is a member of on the password server.
       *
       * We must send 2 SMB requests to do this.  The first is to
       * get the tid (tree ID) of the \\SERVERNAME\IPC$ share.
       * Once we have the tid, we are connected to the share, we
       * can send an RPC request via smb pipes to ask for the
       * names of all groups this user is a member of.
       */

      /* We need the length of the server's name */
      ulen = strlen(pserver);

      /* Setup the SMB with 4 command words, and x data bytes, zero the
       * data bytes*/
      set_message(outbuf, 4, 13 + ulen,True);

      /* Set up the SMB command to connect and X with no flags */
      CVAL(outbuf, smb_com) = SMBtconX;
      CVAL(outbuf, smb_flg) = 0;
      SSVAL(outbuf, smb_flg2,0);
      CVAL(outbuf, smb_vwv0) = 0xFF;

      /* Get the uid from the reply to our login */
      SSVAL(outbuf, smb_uid, SVAL(inbuf, smb_uid));

      /* Set up the 4 words */
      SSVAL(outbuf, smb_tpscnt, 0xFF);       /* Total parm bytes */
      SSVAL(outbuf, smb_tdscnt, 0);          /* Total data bytes */
      SSVAL(outbuf, smb_mprcnt, 0x02);       /* Max Param return bytes
*/
      SSVAL(outbuf, smb_mdrcnt, 1);          /* Password length */

      /* Point to the data area of the smb packet */
      p = &outbuf[smb_tpscnt + 5 * 2];
      *(p++) = 0;              /* Password is empty (null string) */

      *(p++) = '\\';           /* setup share path \\SERVER\IPC$ */
      *(p++) = '\\';
      strcpy(p, pserver);
      strupper(p);
      p += strlen(p);
      strcpy(p, "\\IPC$");
      p += 6;
      strcpy(p, "IPC");

      send_smb(password_client,outbuf);
      ret = receive_smb(password_client,inbuf,5000);

      /* Not checking the response from the connect, but if it
       * failed then the tid we got back will be bad and the
       * request for groups will fail too, so no harm done
       */

      /* Now get the user name length */
      ulen = strlen(user);

      set_message(outbuf,0xE,0x2D + ulen,True);

      /******************************/
      /* send a group query command */
      /******************************/
      CVAL(outbuf, smb_com) = SMBtrans;
      CVAL(outbuf,smb_flg) = 0;
      SSVAL(outbuf,smb_flg2,0x8000);
      CVAL(outbuf,smb_vwv0) = 0xFF;
      SSVAL(outbuf, smb_tid, SVAL(inbuf, smb_tid));
      SSVAL(outbuf, smb_mid, 0x332);

      /* Setup the primary request smb header */
      SSVAL(outbuf, smb_tpscnt, ulen + 18);  /* Total parm bytes */
      SSVAL(outbuf, smb_tdscnt, 0);          /* Total data bytes */
      SSVAL(outbuf, smb_mprcnt, 0x80);       /* Max Param return bytes
*/
      SSVAL(outbuf, smb_mdrcnt, 2100);       /* Max Data Return Bytes */
      SSVAL(outbuf, smb_msrcnt, 0);          /* Max Setup Words */
      SSVAL(outbuf, smb_flags, 0);           /* Transaction Flags */
      SSVAL(outbuf, smb_timeout, 5000);      /* timeout */
      SSVAL(outbuf, smb_pscnt, ulen + 18);   /* Param bytes in this
packet */
      SSVAL(outbuf, smb_psoff, 0x5A);        /* offset to param bytes */
      SSVAL(outbuf, smb_dscnt, 0);           /* Data bytes */
      SSVAL(outbuf, smb_dsoff, 0);           /* Data offset */
      SSVAL(outbuf, smb_suwcnt, 0);          /* Max setup words */

      p = &outbuf[smb_setup1];
      memcpy(p, gpipe, sizeof(gpipe));
      p += sizeof(gpipe);
      strcpy(p, user);
      strupper(p);
      p += ulen + 3;
      p[0] = 0x34;
      p[1] = 0x08;
      memset(p + 2, 0, 20);

      send_smb(password_client,outbuf);
      ret = receive_smb(password_client,inbuf,5000);

      /* See if we successfully got the groups */
      if(ret != 0 &&  CVAL(inbuf,smb_rcls) == 0)
      {
          int plength;
          struct {uchar name[21];} *groups;
          char store_groups[600];
          int numgroups;
          int loop;
          char *grname[100];
          int ingroup = 0;

          p = &inbuf[smb_vwv + (CVAL(inbuf, smb_wct) * 2)];
          plength = *((short *) p);
          numgroups = p[7];

          /* TBD Store the groups away for future validation */


/* later do a group validation such as the following
 *          for(p=strtok(ps_groups, LIST_SEP); p; p = strtok(NULL,
LIST_SEP))
 *          {
 *              for(loop = 0; loop < numgroups; loop++)
 *             {
 *                 if(strcasecmp(p, groups[i].name) == 0)
 *                 {
 *                     DEBUG(3, ("User %s is a member of password
server group %s\n", user, groups[i].name));
 *                     ingroup = 1;
 *                     break;
 *                 }
 *             }
 *         }
 *         if(!ingroup)
 *         {
 *             DEBUG(3, ("User %s is not a member of any of the
password server groups %s\n", user, ps_groups));
 *             return False;
 *         }
 */


      }
      else
      {
          /* Unable to get group list */
          DEBUG(3,("Unable to retrieve groups for user %s from server
%s\n", user, pserver));
      }
  }

  DEBUG(3,("password server %s accepted the password\n",pserver));

#if !KEEP_PASSWORD_SERVER_OPEN
  close(password_client); password_client= -1;
#endif

  return(True);
}





_________________________________________________________
DO YOU YAHOO!?
Get your free @yahoo.com address at http://mail.yahoo.com



More information about the samba mailing list