SAM database "set user info".
[samba.git] / source3 / smbd / ipc.c
index 0c4d0d5bfe79135104e30d004a65782ce806bf0c..5001b16b352be4dbbcf1d0f730ef9ef8074a5ae2 100644 (file)
@@ -61,6 +61,7 @@ extern fstring global_myworkgroup;
 
 extern int Client;
 extern int smb_read_error;
+extern uint32 global_client_caps;
 
 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
                            int mdrcnt,int mprcnt,
@@ -187,9 +188,15 @@ static void send_trans_reply(char *outbuf,
 
        if (buffer_too_large)
        {
-               /* issue a buffer size warning.  on a DCE/RPC pipe, expect an SMBreadX... */
-               SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
-               SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
+               if (global_client_caps & CAP_STATUS32)
+               {
+                       /* issue a buffer size warning.  on a DCE/RPC pipe, expect an SMBreadX... */
+                       SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+                       SIVAL(outbuf, smb_rcls, 0x80000005); /* STATUS_BUFFER_OVERFLOW */
+               } else {
+                       SCVAL(outbuf, smb_rcls, ERRDOS);
+                       SSVAL(outbuf, smb_err, ERRmoredata);
+               }
        }
 
        copy_trans_params_and_data(outbuf, align,
@@ -635,7 +642,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
     pstring fname;
 
     pstrcpy(fname,lp_driverfile());
-    f=fopen(fname,"r");
+    f=sys_fopen(fname,"r");
     if (!f) {
       DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
       desc->errcode=NERR_notsupported;
@@ -741,7 +748,7 @@ static int get_printerdrivernumber(int snum)
   pstrcpy(fname,lp_driverfile());
 
   DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
-  f=fopen(fname,"r");
+  f=sys_fopen(fname,"r");
   if (!f) {
     DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
     return(0);
@@ -842,6 +849,26 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
   if (init_package(&desc,1,count)) {
          desc.subcount = count;
          fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
+  } else if(uLevel == 0) {
+       /*
+        * This is a *disgusting* hack.
+        * This is *so* bad that even I'm embarrassed (and I
+        * have no shame). Here's the deal :
+        * Until we get the correct SPOOLSS code into smbd
+        * then when we're running with NT SMB support then
+        * NT makes this call with a level of zero, and then
+        * immediately follows it with an open request to
+        * the \\SRVSVC pipe. If we allow that open to
+        * succeed then NT barfs when it cannot open the
+        * \\SPOOLSS pipe immediately after and continually
+        * whines saying "Printer name is invalid" forever
+        * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
+        * to fail, then NT downgrades to using the downlevel code
+        * and everything works as well as before. I hate
+        * myself for adding this code.... JRA.
+        */
+
+       fail_next_srvsvc_open();
   }
 
   *rdata_len = desc.usedlen;
@@ -999,7 +1026,7 @@ static int get_server_info(uint32 servertype,
   pstrcat(fname,"/");
   pstrcat(fname,SERVER_LIST);
 
-  f = fopen(fname,"r");
+  f = sys_fopen(fname,"r");
 
   if (!f) {
     DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
@@ -1653,7 +1680,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
    * Older versions of Windows seem to do this.
    */
 
-  if (password_ok(user,pass1,strlen(pass1),NULL) &&
+  if (password_ok(user, pass1,strlen(pass1),NULL, NULL) &&
       chgpasswd(user,pass1,pass2,False))
   {
     SSVAL(*rparam,0,NERR_Success);
@@ -1692,11 +1719,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
                                int *rdata_len,int *rparam_len)
 {
   fstring user;
-  fstring new_passwd;
-  struct smb_passwd *sampw = NULL;
   char *p = param + 2;
-  int ret = True;
-
   *rparam_len = 2;
   *rparam = REALLOC(*rparam,*rparam_len);
 
@@ -1708,13 +1731,13 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
    * Check the parameter definition is correct.
    */
   if(!strequal(param + 2, "zsT")) {
-    DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
+    DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
     return False;
   }
   p = skip_string(p, 1);
 
   if(!strequal(p, "B516B16")) {
-    DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
+    DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
     return False;
   }
   p = skip_string(p,1);
@@ -1736,24 +1759,8 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
    */
   (void)Get_Pwnam( user, True);
 
-  if(check_oem_password( user, (unsigned char *)data, &sampw, 
-                         new_passwd, (int)sizeof(new_passwd)) == False) {
-    return True;
-  }
-
-  /* 
-   * At this point we have the new case-sensitive plaintext
-   * password in the fstring new_passwd. If we wanted to synchronise
-   * with UNIX passwords we would call a UNIX password changing 
-   * function here. However it would have to be done as root
-   * as the plaintext of the old users password is not 
-   * available. JRA.
-   */
-
-  if(lp_unix_password_sync())
-    ret = chgpasswd(user,"", new_passwd, True);
-  if(ret && change_oem_password( sampw, new_passwd, False)) {
+  if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
+  {
     SSVAL(*rparam,0,NERR_Success);
   }
 
@@ -3121,9 +3128,33 @@ static void api_rpc_trans_reply(char *outbuf,
                /* all of data was sent: no need to wait for SMBreadX calls */
                mem_free_data(p->rhdr .data);
                mem_free_data(p->rdata.data);
+               mem_free_data(p->rdata_i.data);
+       }
+}
+
+/****************************************************************************
+ WaitNamedPipeHandleState 
+****************************************************************************/
+static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param)
+{
+       uint16 priority;
+
+       if (!param) return False;
+
+       priority = param[0] + (param[1] << 8);
+       DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
+
+       if (wait_rpc_pipe_hnd_state(p, priority))
+       {
+               /* now send the reply */
+               send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
+
+               return True;
        }
+       return False;
 }
 
+
 /****************************************************************************
  SetNamedPipeHandleState 
 ****************************************************************************/
@@ -3134,7 +3165,7 @@ static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
        if (!param) return False;
 
        id = param[0] + (param[1] << 8);
-       DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
+       DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
 
        if (set_rpc_pipe_hnd_state(p, id))
        {
@@ -3187,20 +3218,12 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
        int subcommand;
        pipes_struct *p = NULL;
        prs_struct pd;
-       struct mem_buf data_buf;
 
        DEBUG(5,("api_fd_reply\n"));
 
-       /* fake up a data buffer from the api_fd_reply data parameters */
-       mem_create(&data_buf, data, tdscnt, 0, False);
-       data_buf.offset.start = 0;
-       data_buf.offset.end   = tdscnt;
-
-       /* fake up a parsing structure */
-       pd.data = &data_buf;
-       pd.align = 4;
-       pd.io = True;
-       pd.offset = 0;
+       /* make a static data parsing structure from the api_fd_reply data */
+       prs_init(&pd, 0, 4, 0, True);
+       mem_create(pd.data, data, 0, tdscnt, 0, False);
 
        /* First find out the name of this file. */
        if (suwcnt != 2)
@@ -3220,7 +3243,8 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
                                  subcommand, p->name, pnum));
 
                /* record maximum data length that can be transmitted in an SMBtrans */
-               p->file_offset = mdrcnt;
+               p->file_offset          = mdrcnt;
+               p->prev_pdu_file_offset = 0;
 
                 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
                            p, p->file_offset));
@@ -3237,6 +3261,12 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
                                }
                                break;
                        }
+                       case 0x53:
+                       {
+                               /* Wait Named Pipe Handle state */
+                               reply = api_WNPHS(outbuf, p, params);
+                               break;
+                       }
                        case 0x01:
                        {
                                /* Set Named Pipe Handle state */
@@ -3250,6 +3280,8 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
                DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
        }
 
+       mem_free_data(pd.data);
+
        if (!reply)
        {
                return api_no_reply(outbuf, mdrcnt);
@@ -3401,14 +3433,8 @@ static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data
                    &rdata,&rparam,&rdata_len,&rparam_len);
 
       
-  mem_create(&rdata_buf , rdata , rdata_len , 0, False);
-  mem_create(&rparam_buf, rparam, rparam_len, 0, False);
-
-  rdata_buf.offset.start = 0;
-  rdata_buf.offset.end   = rdata_len;
-
-  rparam_buf.offset.start = 0;
-  rparam_buf.offset.end   = rparam_len;
+  mem_create(&rdata_buf , rdata , 0, rdata_len , 0, False);
+  mem_create(&rparam_buf, rparam, 0, rparam_len, 0, False);
 
   /* now send the reply */
   send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
@@ -3434,6 +3460,16 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na
                return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
        }
 
+       if (strequal(name,"WKSSVC") ||
+           strequal(name,"SRVSVC") ||
+           strequal(name,"WINREG") ||
+           strequal(name,"SAMR") ||
+           strequal(name,"LSARPC"))
+       {
+               DEBUG(4,("named pipe command from Win95 (wow!)\n"));
+               return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
+       }
+
        if (strlen(name) < 1)
        {
                return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
@@ -3454,6 +3490,7 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na
 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
 {
        fstring name;
+        int name_offset = 0;
        char *data=NULL,*params=NULL;
        uint16 *setup=NULL;
        int outsize = 0;
@@ -3563,10 +3600,19 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
                 name,tdscnt,tpscnt,suwcnt));
        
-       if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
+        /*
+         * WinCE wierdness....
+         */
+
+        if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine,
+                                strlen(local_machine)) == 0)) {
+          name_offset = strlen(local_machine)+1;
+        }
+
+       if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
                DEBUG(5,("calling named_pipe\n"));
                outsize = named_pipe(conn,vuid,outbuf,
-                                    name+strlen("\\PIPE\\"),setup,data,params,
+                                    name+name_offset+strlen("\\PIPE\\"),setup,data,params,
                                     suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
        } else {
                DEBUG(3,("invalid pipe name\n"));