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