Apache-AuthenNTLM

 view release on metacpan or  search on metacpan

smb/smbval/smblib-util.c  view on Meta::CPAN


  /* The -1 accounts for the one byte smb_buf we have because some systems */
  /* don't like char msg_buf[]                                             */

  pkt_len = SMB_negp_len + prots_len;

  /* Make sure that the pkt len is long enough for the max response ...   */
  /* Which is a problem, because the encryption key len eec may be long   */

  if (pkt_len < (SMB_hdr_wct_offset + (19 * 2) + 40)) {

    alloc_len = SMB_hdr_wct_offset + (19 * 2) + 40;

  }
  else {

    alloc_len = pkt_len;

  }

  pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(alloc_len);

  if (pkt == NULL) {

    SMBlib_errno = SMBlibE_NoSpace;
    return(SMBlibE_BAD);

  }

  /* Now plug in the bits we need */

  bzero(SMB_Hdr(pkt), SMB_negp_len);
  SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF);  /* Plunk in IDF */
  *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBnegprot;
  SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid);
  SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
  SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid);
  SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid);
  *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 0;

  SSVAL(SMB_Hdr(pkt), SMB_negp_bcc_offset, prots_len);

  /* Now copy the prot strings in with the right stuff */

  p = (char *)(SMB_Hdr(pkt) + SMB_negp_buf_offset);

  for (i = 0; Prots[i] != NULL; i++) {

    *p = SMBdialectID;
    strcpy(p + 1, Prots[i]);
    p = p + strlen(Prots[i]) + 2; /* Adjust len of p for null plus dialectID */

  }

  /* Now send the packet and sit back ... */

  if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0){


#ifdef DEBUG
    fprintf(stderr, "Error sending negotiate protocol\n");
#endif

    RFCNB_Free_Pkt(pkt);
    SMBlib_errno = -SMBlibE_SendFailed; /* Failed, check lower layer errno */
    return(SMBlibE_BAD);

  }

  /* Now get the response ... */

  if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, alloc_len) < 0) {

#ifdef DEBUG
    fprintf(stderr, "Error receiving response to negotiate\n");
#endif

    RFCNB_Free_Pkt(pkt);
    SMBlib_errno = -SMBlibE_RecvFailed; /* Failed, check lower layer errno */
    return(SMBlibE_BAD);

  }

  if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) {  /* Process error */

#ifdef DEBUG
    fprintf(stderr, "SMB_Negotiate failed with errorclass = %i, Error Code = %i\n",
	    CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
	    SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
#endif

    SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
    RFCNB_Free_Pkt(pkt);
    SMBlib_errno = SMBlibE_Remote;
    return(SMBlibE_BAD);

  }
  
  if (SVAL(SMB_Hdr(pkt), SMB_negrCP_idx_offset) == 0xFFFF) {

#ifdef DEBUG
    fprintf(stderr, "None of our protocols was accepted ... ");
#endif

    RFCNB_Free_Pkt(pkt);
    SMBlib_errno = SMBlibE_NegNoProt;
    return(SMBlibE_BAD);

  }

  /* Now, unpack the info from the response, if any and evaluate the proto */
  /* selected. We must make sure it is one we like ...                     */

  Con_Handle -> prot_IDX = prot = SVAL(SMB_Hdr(pkt), SMB_negrCP_idx_offset);
  Con_Handle -> protocol = SMB_Figure_Protocol(Prots, prot);

  if (Con_Handle -> protocol == SMB_P_Unknown) { /* No good ... */

    RFCNB_Free_Pkt(pkt);
    SMBlib_errno = SMBlibE_ProtUnknown;
    return(SMBlibE_BAD);

  }
  
  switch (CVAL(SMB_Hdr(pkt), SMB_hdr_wct_offset)) {

  case 0x01:      /* No more info ... */

    break;

  case 13:        /* Up to and including LanMan 2.1 */

    Con_Handle -> Security = SVAL(SMB_Hdr(pkt), SMB_negrLM_sec_offset);
    Con_Handle -> encrypt_passwords = ((Con_Handle -> Security & SMB_sec_encrypt_mask) != 0x00);
    Con_Handle -> Security = Con_Handle -> Security & SMB_sec_user_mask;

    Con_Handle -> max_xmit = SVAL(SMB_Hdr(pkt), SMB_negrLM_mbs_offset);
    Con_Handle -> MaxMPX = SVAL(SMB_Hdr(pkt), SMB_negrLM_mmc_offset);
    Con_Handle -> MaxVC = SVAL(SMB_Hdr(pkt), SMB_negrLM_mnv_offset);
    Con_Handle -> Raw_Support = SVAL(SMB_Hdr(pkt), SMB_negrLM_rm_offset);
    Con_Handle -> SessionKey = IVAL(SMB_Hdr(pkt), SMB_negrLM_sk_offset);
    Con_Handle -> SvrTZ = SVAL(SMB_Hdr(pkt), SMB_negrLM_stz_offset);
    Con_Handle -> Encrypt_Key_Len = SVAL(SMB_Hdr(pkt), SMB_negrLM_ekl_offset);
    
    p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset);
    fprintf(stderr, "%d", (char *)(SMB_Hdr(pkt) + SMB_negrLM_buf_offset));
    memcpy(Con_Handle->Encrypt_Key, p, 8);

    p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset + Con_Handle -> Encrypt_Key_Len);

    strncpy(p, Con_Handle -> Svr_PDom, sizeof(Con_Handle -> Svr_PDom) - 1);

    break;

  case 17:        /* NT LM 0.12 and LN LM 1.0 */

    Con_Handle -> Security = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_sec_offset);
    Con_Handle -> encrypt_passwords = ((Con_Handle -> Security & SMB_sec_encrypt_mask) != 0x00);
    Con_Handle -> Security = Con_Handle -> Security & SMB_sec_user_mask;

    Con_Handle -> max_xmit = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_mbs_offset);
    Con_Handle -> MaxMPX = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_mmc_offset);
    Con_Handle -> MaxVC = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_mnv_offset);
    Con_Handle -> MaxRaw = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_mrs_offset);
    Con_Handle -> SessionKey = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_sk_offset);
    Con_Handle -> SvrTZ = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_stz_offset);
    Con_Handle -> Encrypt_Key_Len = CVAL(SMB_Hdr(pkt), SMB_negrNTLM_ekl_offset);

    p = (SMB_Hdr(pkt) + SMB_negrNTLM_buf_offset );
    memcpy(Con_Handle -> Encrypt_Key, p, 8);
    p = (SMB_Hdr(pkt) + SMB_negrNTLM_buf_offset + Con_Handle -> Encrypt_Key_Len);

    strncpy(p, Con_Handle -> Svr_PDom, sizeof(Con_Handle -> Svr_PDom) - 1);

    break;

  default:

#ifdef DEBUG
    fprintf(stderr, "Unknown NegProt response format ... Ignored\n");
    fprintf(stderr, "  wct = %i\n", CVAL(SMB_Hdr(pkt), SMB_hdr_wct_offset));
#endif

    break;
  }

#ifdef DEBUG
  fprintf(stderr, "Protocol selected is: %i:%s\n", prot, Prots[prot]);
#endif

  RFCNB_Free_Pkt(pkt);
  return(0);

}

/* Get our hostname */

void SMB_Get_My_Name(char *name, int len)

{ 
  /* int loc; */

  if (gethostname(name, len) < 0) { /* Error getting name */

    strncpy(name, "unknown", len);

    /* Should check the error */

#ifdef DEBUG
    fprintf(stderr, "gethostname in SMB_Get_My_Name returned error:");
    perror("");
#endif

  }

  /* only keep the portion up to the first "." */


}

/* Send a TCON to the remote server ...               */

SMB_Tree_Handle SMB_TreeConnect(SMB_Handle_Type Con_Handle, 
				SMB_Tree_Handle Tree_Handle,
				char *path, 
				char *password,
				char *device)

{ struct RFCNB_Pkt *pkt;
  int param_len, i, pkt_len;
  char *p;
  SMB_Tree_Handle tree;

  /* Figure out how much space is needed for path, password, dev ... */

  if (path == NULL || password == NULL || device == NULL) {

#ifdef DEBUG
    fprintf(stderr, "Bad parameter passed to SMB_TreeConnect\n");
#endif

    SMBlib_errno = SMBlibE_BadParam;
    return(NULL);

  }

  /* The + 2 is because of the \0 and the marker ...                    */

  param_len = strlen(path) + 2 + strlen(password) + 2 + strlen(device) + 2;

  /* The -1 accounts for the one byte smb_buf we have because some systems */
  /* don't like char msg_buf[]                                             */

  pkt_len = SMB_tcon_len + param_len;

  pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);

  if (pkt == NULL) {

    SMBlib_errno = SMBlibE_NoSpace;
    return(NULL); /* Should handle the error */

  }

  /* Now allocate a tree for this to go into ... */

  if (Tree_Handle == NULL) {

    tree = (SMB_Tree_Handle)malloc(sizeof(struct SMB_Tree_Structure));

    if (tree == NULL) {
    
      RFCNB_Free_Pkt(pkt);
      SMBlib_errno = SMBlibE_NoSpace;
      return(NULL);
      
    }
  }
  else {

    tree = Tree_Handle;

  }

  tree -> next = tree -> prev = NULL;
  tree -> con = Con_Handle;
  strncpy(tree -> path, path, sizeof(tree -> path));
  strncpy(tree -> device_type, device, sizeof(tree -> device_type));

  /* Now plug in the values ... */

  bzero(SMB_Hdr(pkt), SMB_tcon_len);
  SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF);  /* Plunk in IDF */
  *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBtcon;
  SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid);
  SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
  SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid);
  SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid);
  *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 0;

  SSVAL(SMB_Hdr(pkt), SMB_tcon_bcc_offset, param_len);

  /* Now copy the param strings in with the right stuff */

  p = (char *)(SMB_Hdr(pkt) + SMB_tcon_buf_offset);
  *p = SMBasciiID;
  strcpy(p + 1, path);
  p = p + strlen(path) + 2;
  *p = SMBasciiID;
  strcpy(p + 1, password);
  p = p + strlen(password) + 2;
  *p = SMBasciiID;
  strcpy(p + 1, device);

  /* Now send the packet and sit back ... */

  if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0){

#ifdef DEBUG
    fprintf(stderr, "Error sending TCon request\n");
#endif

    if (Tree_Handle == NULL)
      free(tree);
    RFCNB_Free_Pkt(pkt);
    SMBlib_errno = -SMBlibE_SendFailed;
    return(NULL);

  }

  /* Now get the response ... */

  if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) {

#ifdef DEBUG
    fprintf(stderr, "Error receiving response to TCon\n");
#endif

    if (Tree_Handle == NULL) 
      free(tree);
    RFCNB_Free_Pkt(pkt);
    SMBlib_errno = -SMBlibE_RecvFailed;
    return(NULL);

  }

  /* Check out the response type ... */

  if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) {  /* Process error */

#ifdef DEBUG
    fprintf(stderr, "SMB_TCon failed with errorclass = %i, Error Code = %i\n",
	    CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
	    SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
#endif

    if (Tree_Handle == NULL)
      free(tree);
    SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
    RFCNB_Free_Pkt(pkt);
    SMBlib_errno = SMBlibE_Remote;
    return(NULL);

  }

  tree -> tid = SVAL(SMB_Hdr(pkt), SMB_tconr_tid_offset);
  tree -> mbs = SVAL(SMB_Hdr(pkt), SMB_tconr_mbs_offset);

#ifdef DEBUG
  fprintf(stderr, "TConn succeeded, with TID=%i, Max Xmit=%i\n",
                 tree -> tid, tree -> mbs);
#endif

  /* Now link the Tree to the Server Structure ... */

  if (Con_Handle -> first_tree == NULL) {

    Con_Handle -> first_tree = tree;
    Con_Handle -> last_tree = tree;

  }
  else {

    Con_Handle -> last_tree -> next = tree;
    tree -> prev = Con_Handle -> last_tree;
    Con_Handle -> last_tree = tree;

  }

  RFCNB_Free_Pkt(pkt);
  return(tree); 

}

int SMB_TreeDisconnect(SMB_Tree_Handle Tree_Handle, BOOL discard)

{ struct RFCNB_Pkt *pkt;
  int pkt_len;

  pkt_len = SMB_tdis_len;

  pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);

  if (pkt == NULL) {

    SMBlib_errno = SMBlibE_NoSpace;
    return(SMBlibE_BAD); /* Should handle the error */

  }

  /* Now plug in the values ... */

  bzero(SMB_Hdr(pkt), SMB_tdis_len);
  SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF);  /* Plunk in IDF */
  *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBtdis;
  SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Tree_Handle -> con -> pid);
  SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Tree_Handle -> con -> mid);
  SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Tree_Handle -> con -> uid);
  *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 0;

  SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, Tree_Handle -> tid);
  SSVAL(SMB_Hdr(pkt), SMB_tcon_bcc_offset, 0);

  /* Now send the packet and sit back ... */

  if (RFCNB_Send(Tree_Handle -> con -> Trans_Connect, pkt, pkt_len) < 0){

#ifdef DEBUG
    fprintf(stderr, "Error sending TDis request\n");
#endif

    RFCNB_Free_Pkt(pkt);
    SMBlib_errno = -SMBlibE_SendFailed;
    return(SMBlibE_BAD);

  }

  /* Now get the response ... */

  if (RFCNB_Recv(Tree_Handle -> con -> Trans_Connect, pkt, pkt_len) < 0) {

#ifdef DEBUG
    fprintf(stderr, "Error receiving response to TCon\n");
#endif

    RFCNB_Free_Pkt(pkt);
    SMBlib_errno = -SMBlibE_RecvFailed;
    return(SMBlibE_BAD);

  }

  /* Check out the response type ... */

  if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) {  /* Process error */

#ifdef DEBUG
    fprintf(stderr, "SMB_TDis failed with errorclass = %i, Error Code = %i\n",
	    CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
	    SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
#endif

    SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
    RFCNB_Free_Pkt(pkt);
    SMBlib_errno = SMBlibE_Remote;
    return(SMBlibE_BAD);

  }

  Tree_Handle -> tid = 0xFFFF;        /* Invalid TID */
  Tree_Handle -> mbs = 0;             /* Invalid     */

#ifdef DEBUG

  fprintf(stderr, "Tree disconnect successful ...\n");

#endif

  /* What about the tree handle ? */

  if (discard == TRUE) { /* Unlink it and free it ... */

    if (Tree_Handle -> next == NULL)
      Tree_Handle -> con -> first_tree = Tree_Handle -> prev;
    else
      Tree_Handle -> next -> prev = Tree_Handle -> prev;

    if (Tree_Handle -> prev == NULL)
      Tree_Handle -> con -> last_tree = Tree_Handle -> next;
    else
      Tree_Handle -> prev -> next = Tree_Handle -> next;

  }

  RFCNB_Free_Pkt(pkt);
  return(0);

}

/* Pick up the last LMBlib error ... */

int SMB_Get_Last_Error()

{

  return(SMBlib_errno);

}

/* Pick up the last error returned in an SMB packet          */
/* We will need macros to extract error class and error code */

int SMB_Get_Last_SMB_Err()

{

  return(SMBlib_SMB_Error);

}

/* Pick up the error message associated with an error from SMBlib  */

/* Keep this table in sync with the message codes in smblib-common.h */

static char *SMBlib_Error_Messages[] = {

  "Request completed sucessfully.",
  "Server returned a non-zero SMB Error Class and Code.",
  "A lower layer protocol error occurred.",
  "Function not yet implemented.",
  "The protocol negotiated does not support the request.",
  "No space available for operation.",
  "One or more bad parameters passed.",
  "None of the protocols we offered were accepted.",
  "The attempt to send an SMB request failed. See protocol error info.",



( run in 2.290 seconds using v1.01-cache-2.11-cpan-0d23b851a93 )