Kill off the old varient of 'check_plaintext_password' (new version just
[ira/wip.git] / source3 / smbd / lanman.c
index 0d92c98628d93a08f8e28f79354fdae0ad9f6eaa..1a5777e1d4bb49d5a8d9dbf1e0f61b348d7414e9 100644 (file)
@@ -1512,7 +1512,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
   if (uLevel > 0)
     {
       int type;
-      CVAL(p,13) = 0;
+      SCVAL(p,13,0);
       type = STYPE_DISKTREE;
       if (lp_print_ok(snum)) type = STYPE_PRINTQ;
       if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
@@ -1670,62 +1670,63 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
   fstring sharename;
   fstring comment;
   pstring pathname;
-  pstring command;
-  int offset;
+  char *command, *cmdname;
+  uint offset;
   int snum;
-  int res;
+  int res = ERRunsup;
   
   /* check it's a supported varient */
   if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
   if (!check_share_info(uLevel,str2)) return False;
-  if (uLevel != 2) {
-    *rparam_len = 4;
-    *rparam = REALLOC(*rparam,*rparam_len);
-    *rdata_len = 0;
-    SSVAL(*rparam,0,NERR_notsupported);
-    SSVAL(*rparam,2,0);
-    return True;
-  }
+  if (uLevel != 2) return False;
 
   pull_ascii_fstring(sharename,data);
   snum = find_service(sharename);
   if (snum >= 0) { /* already exists */
-    *rparam_len = 4;
-    *rparam = REALLOC(*rparam,*rparam_len);
-    SSVAL(*rparam,0,ERRfilexists);
-    SSVAL(*rparam,2,0);
-    return True;
+    res = ERRfilexists;
+    goto error_exit;
   }
 
   /* only support disk share adds */
-  if (SVAL(data,14)!=STYPE_DISKTREE) {
-    *rparam_len = 4;
-    *rparam = REALLOC(*rparam,*rparam_len);
-    *rdata_len = 0;
-    SSVAL(*rparam,0,NERR_notsupported);
-    SSVAL(*rparam,2,0);
-    return True;
-  }
+  if (SVAL(data,14)!=STYPE_DISKTREE) return False;
 
   offset = IVAL(data, 16);
+  if (offset >= mdrcnt) {
+    res = ERRinvalidparam;
+    goto error_exit;
+  }
   pull_ascii_fstring(comment, offset? (data+offset) : "");
+
   offset = IVAL(data, 26);
+  if (offset >= mdrcnt) {
+    res = ERRinvalidparam;
+    goto error_exit;
+  }
   pull_ascii_pstring(pathname, offset? (data+offset) : "");
 
   string_replace(sharename, '"', ' ');
   string_replace(pathname, '"', ' ');
   string_replace(comment, '"', ' ');
 
-  slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
-          lp_add_share_cmd(), CONFIGFILE, sharename, pathname, comment);
+  cmdname = lp_add_share_cmd();
 
-  DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
-  if ((res = smbrun(command, NULL)) != 0) {
-    DEBUG(0,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
-    return ERRnoaccess;
-  } else
-    message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False);
-  return True;
+  if (!cmdname || *cmdname == '\0') return False;
+
+  asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
+          lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
+
+  if (command) {
+    DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
+    if ((res = smbrun(command, NULL)) != 0) {
+      DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
+      SAFE_FREE(command);
+      res = ERRnoaccess;
+      goto error_exit;
+    } else {
+      SAFE_FREE(command);
+      message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
+    }
+  } else return False;
 
   *rparam_len = 6;
   *rparam = REALLOC(*rparam,*rparam_len);
@@ -1734,7 +1735,16 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
   SSVAL(*rparam,4,*rdata_len);
   *rdata_len = 0;
   
-  return(True);
+  return True;
+
+ error_exit:
+  *rparam_len = 4;
+  *rparam = REALLOC(*rparam,*rparam_len);
+  *rdata_len = 0;
+  SSVAL(*rparam,0,res);
+  SSVAL(*rparam,2,0);
+  return True;
+
 }
 
 /****************************************************************************
@@ -1884,16 +1894,16 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch
     t = LocalTime(&unixdate);
 
     SIVAL(p,4,0);              /* msecs ? */
-    CVAL(p,8) = t->tm_hour;
-    CVAL(p,9) = t->tm_min;
-    CVAL(p,10) = t->tm_sec;
-    CVAL(p,11) = 0;            /* hundredths of seconds */
+    SCVAL(p,8,t->tm_hour);
+    SCVAL(p,9,t->tm_min);
+    SCVAL(p,10,t->tm_sec);
+    SCVAL(p,11,0);             /* hundredths of seconds */
     SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
     SSVAL(p,14,10000);         /* timer interval in 0.0001 of sec */
-    CVAL(p,16) = t->tm_mday;
-    CVAL(p,17) = t->tm_mon + 1;
+    SCVAL(p,16,t->tm_mday);
+    SCVAL(p,17,t->tm_mon + 1);
     SSVAL(p,18,1900+t->tm_year);
-    CVAL(p,20) = t->tm_wday;
+    SCVAL(p,20,t->tm_wday);
   }
 
 
@@ -1913,8 +1923,6 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
   fstring user;
   fstring pass1,pass2;
 
-  struct passwd *passwd;
-
   pull_ascii_fstring(user,p);
 
   p = skip_string(p,1);
@@ -1934,68 +1942,43 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
 
   DEBUG(3,("Set password for <%s>\n",user));
 
-  /*
-   * Pass the user through the NT -> unix user mapping
-   * function.
-   */
-
-  (void)map_username(user);
-
-  /*
-   * Do any UNIX username case mangling.
-   */
-  passwd = Get_Pwnam( user, True);
-
   /*
    * Attempt to verify the old password against smbpasswd entries
    * Win98 clients send old and new password in plaintext for this call.
    */
 
   {
-    fstring saved_pass2;
-    SAM_ACCOUNT *sampass=NULL;
-
-    /*
-     * Save the new password as change_oem_password overwrites it
-     * with zeros.
-     */
-
-    fstrcpy(saved_pass2, pass2);
-
-    if (check_plaintext_password(user,pass1,strlen(pass1),&sampass) &&
-        change_oem_password(sampass,pass2))
-    {
-      SSVAL(*rparam,0,NERR_Success);
-
-      /*
-       * If unix password sync was requested, attempt to change
-       * the /etc/passwd database also. Return failure if this cannot
-       * be done.
-       */
-
-      if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
-        SSVAL(*rparam,0,NERR_badpass);
-    }
-       pdb_free_sam(&sampass);
- }
-  
-
-  /*
-   * If the above failed, attempt the plaintext password change.
-   * This tests against the /etc/passwd database only.
-   */
-
-  if(SVAL(*rparam,0) != NERR_Success)
-  {
-         if NT_STATUS_IS_OK(pass_check(passwd, user, pass1, 
-                                       strlen(pass1), NULL, False)) 
+         auth_serversupplied_info *server_info = NULL;
+         DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
+         if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
+                 if (change_oem_password(server_info->sam_account,pass2))
                  {
-                         if (chgpasswd(user,pass1,pass2,False)) {
-                                 SSVAL(*rparam,0,NERR_Success);
-                         }
+                         SSVAL(*rparam,0,NERR_Success);
                  }
+                 
+                 /*
+                  * If unix password sync was requested, attempt to change
+                  * the /etc/passwd database also. Return failure if this cannot
+                  * be done.
+                  *
+                  * This occours regardless of the previous result, becouse 
+                  * It might not have been testing the password against the SAM backend.
+                  * (and therefore the change_oem_password would fail).
+                  *
+                  * Conditional on lp_unix_password_sync() becouse we don't want
+                   * to touch the unix db unless we have admin permission.
+                  */
+                 
+                 if(lp_unix_password_sync() && !chgpasswd(pdb_get_username(server_info->sam_account),
+                                                          pass1,pass2,False)) {
+                         SSVAL(*rparam,0,NERR_badpass);
+                 }
+                 
+                 free_server_info(&server_info);
+         }
+         data_blob_clear_free(&password);
   }
-  
+
   /*
    * If the plaintext change failed, attempt
    * the old encrypted method. NT will generate this
@@ -2072,7 +2055,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
   /*
    * Do any UNIX username case mangling.
    */
-  (void)Get_Pwnam( user, True);
+  (void)Get_Pwnam_Modify( user );
 
   if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
   {
@@ -3405,6 +3388,110 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
   return(True);
 }
 
+struct session_info {
+  char machine[31];
+  char username[24];
+  char clitype[24];
+  int opens;
+  int time;
+};
+
+struct sessions_info {
+  int count;
+  struct session_info *session_list;
+};
+
+static int gather_sessioninfo(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
+{
+  struct sessions_info *sinfo = state;
+  struct session_info *curinfo = NULL;
+  struct sessionid *sessid = (struct sessionid *) dbuf.dptr;
+
+  sinfo->count += 1;
+  sinfo->session_list = REALLOC(sinfo->session_list, sinfo->count * sizeof(struct session_info));
+
+  curinfo = &(sinfo->session_list[sinfo->count - 1]);
+
+  safe_strcpy(curinfo->machine, sessid->remote_machine, 
+             sizeof(curinfo->machine));
+  safe_strcpy(curinfo->username, uidtoname(sessid->uid), 
+         sizeof(curinfo->username));
+  DEBUG(7,("gather_sessioninfo session from %s@%s\n", 
+          curinfo->username, curinfo->machine));
+  return 0;
+}
+
+/****************************************************************************
+ List open sessions
+ ****************************************************************************/
+static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
+                              int mdrcnt,int mprcnt,
+                              char **rdata,char **rparam,
+                              int *rdata_len,int *rparam_len)
+
+{
+  char *str1 = param+2;
+  char *str2 = skip_string(str1,1);
+  char *p = skip_string(str2,1);
+  int uLevel;
+  struct pack_desc desc;
+  struct sessions_info sinfo;
+  int i;
+
+  memset((char *)&desc,'\0',sizeof(desc));
+
+  uLevel = SVAL(p,0);
+
+  DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
+  DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
+  DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
+
+  /* check it's a supported varient */
+  if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
+  if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
+
+  sinfo.count = 0;
+  sinfo.session_list = NULL;
+
+  if (!session_traverse(gather_sessioninfo, &sinfo)) {
+    DEBUG(4,("RNetSessionEnum session_traverse failed\n"));
+    return False;
+  }
+
+  if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
+  memset((char *)&desc,'\0',sizeof(desc));
+  desc.base = *rdata;
+  desc.buflen = mdrcnt;
+  desc.format = str2;
+  if (!init_package(&desc,sinfo.count,0)) {
+    return False;
+  }
+
+  for(i=0; i<sinfo.count; i++) {
+    PACKS(&desc, "z", sinfo.session_list[i].machine);
+    PACKS(&desc, "z", sinfo.session_list[i].username);
+    PACKI(&desc, "W", 1); /* num conns */
+    PACKI(&desc, "W", 0); /* num opens */
+    PACKI(&desc, "W", 1); /* num users */
+    PACKI(&desc, "D", 0); /* session time */
+    PACKI(&desc, "D", 0); /* idle time */
+    PACKI(&desc, "D", 0); /* flags */
+    PACKS(&desc, "z", "Unknown Client"); /* client type string */
+  }
+
+  *rdata_len = desc.usedlen;
+
+  *rparam_len = 8;
+  *rparam = REALLOC(*rparam,*rparam_len);
+  SSVALS(*rparam,0,desc.errcode);
+  SSVAL(*rparam,2,0); /* converter */
+  SSVAL(*rparam,4,sinfo.count); /* count */
+
+  DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
+  return True;
+}
+
+
 /****************************************************************************
  The buffer was too small
  ****************************************************************************/
@@ -3463,6 +3550,7 @@ struct
   {"RNetShareEnum",    RAP_WshareEnum,         api_RNetShareEnum,0},
   {"RNetShareGetInfo", RAP_WshareGetInfo,      api_RNetShareGetInfo,0},
   {"RNetShareAdd",     RAP_WshareAdd,          api_RNetShareAdd,0},
+  {"RNetSessionEnum",  RAP_WsessionEnum,       api_RNetSessionEnum,0},
   {"RNetServerGetInfo",        RAP_WserverGetInfo,     api_RNetServerGetInfo,0},
   {"RNetGroupEnum",    RAP_WGroupEnum,         api_RNetGroupEnum,0},
   {"RNetGroupGetUsers", RAP_WGroupGetUsers,    api_RNetGroupGetUsers,0},