📄 smblib-util.c
字号:
/* UNIX SMBlib NetBIOS implementation * * Version 1.0 * SMBlib Utility Routines * * Copyright (C) Richard Sharpe 1996 * *//* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "smblib-priv.h"#include <string.h>#include "rfcnb.h"/* global data structures */static int SMB_Types[] ={SMB_P_Core, SMB_P_CorePlus, SMB_P_DOSLanMan1, SMB_P_DOSLanMan1, SMB_P_LanMan1, SMB_P_DOSLanMan2, SMB_P_LanMan2, SMB_P_LanMan2_1, SMB_P_LanMan2_1, SMB_P_NT1, SMB_P_NT1, SMB_P_NT1, -1};static char *SMB_Prots[] ={"PC NETWORK PROGRAM 1.0", "MICROSOFT NETWORKS 1.03", "MICROSOFT NETWORKS 3.0", "DOS LANMAN1.0", "LANMAN1.0", "DOS LM1.2X002", "LM1.2X002", "DOS LANMAN2.1", "LANMAN2.1", "Samba", "NT LM 0.12", "NT LANMAN 1.0", NULL};/* Print out an SMB pkt in all its gory detail ... */voidSMB_Print_Pkt(FILE fd, RFCNB_Pkt * pkt, BOOL command, int Offset, int Len){ /* Well, just how do we do this ... print it I suppose */ /* Print out the SMB header ... */ /* Print the command */ /* Print the other bits in the header */ /* etc */}/* Convert a DOS Date_Time to a local host type date time for printing */char *SMB_DOSTimToStr(int DOS_time){ static char SMB_Time_Temp[48]; int DOS_sec, DOS_min, DOS_hour, DOS_day, DOS_month, DOS_year; SMB_Time_Temp[0] = 0; DOS_sec = (DOS_time & 0x001F) * 2; DOS_min = (DOS_time & 0x07E0) >> 5; DOS_hour = ((DOS_time & 0xF800) >> 11); DOS_day = (DOS_time & 0x001F0000) >> 16; DOS_month = (DOS_time & 0x01E00000) >> 21; DOS_year = ((DOS_time & 0xFE000000) >> 25) + 80; sprintf(SMB_Time_Temp, "%2d/%02d/%2d %2d:%02d:%02d", DOS_day, DOS_month, DOS_year, DOS_hour, DOS_min, DOS_sec); return (SMB_Time_Temp);}/* Convert an attribute byte/word etc to a string ... We return a pointer * to a static string which we guarantee is long enough. If verbose is * true, we print out long form of strings ... */char *SMB_AtrToStr(int attribs, BOOL verbose){ static char SMB_Attrib_Temp[128]; SMB_Attrib_Temp[0] = 0; if (attribs & SMB_FA_ROF) strcat(SMB_Attrib_Temp, (verbose ? "Read Only " : "R")); if (attribs & SMB_FA_HID) strcat(SMB_Attrib_Temp, (verbose ? "Hidden " : "H")); if (attribs & SMB_FA_SYS) strcat(SMB_Attrib_Temp, (verbose ? "System " : "S")); if (attribs & SMB_FA_VOL) strcat(SMB_Attrib_Temp, (verbose ? "Volume " : "V")); if (attribs & SMB_FA_DIR) strcat(SMB_Attrib_Temp, (verbose ? "Directory " : "D")); if (attribs & SMB_FA_ARC) strcat(SMB_Attrib_Temp, (verbose ? "Archive " : "A")); return (SMB_Attrib_Temp);}/* Pick up the Max Buffer Size from the Tree Structure ... */intSMB_Get_Tree_MBS(SMB_Tree_Handle tree){ if (tree != NULL) { return (tree->mbs); } else { return (SMBlibE_BAD); }}/* Pick up the Max buffer size */intSMB_Get_Max_Buf_Siz(SMB_Handle_Type Con_Handle){ if (Con_Handle != NULL) { return (Con_Handle->max_xmit); } else { return (SMBlibE_BAD); }}/* Pickup the protocol index from the connection structure */intSMB_Get_Protocol_IDX(SMB_Handle_Type Con_Handle){ if (Con_Handle != NULL) { return (Con_Handle->prot_IDX); } else { return (0xFFFF); /* Invalid protocol */ }}/* Pick up the protocol from the connection structure */intSMB_Get_Protocol(SMB_Handle_Type Con_Handle){ if (Con_Handle != NULL) { return (Con_Handle->protocol); } else { return (0xFFFF); /* Invalid protocol */ }}/* Figure out what protocol was accepted, given the list of dialect strings *//* We offered, and the index back from the server. We allow for a user *//* supplied list, and assume that it is a subset of our list */intSMB_Figure_Protocol(char *dialects[], int prot_index){ int i; if (dialects == SMB_Prots) { /* The jobs is easy, just index into table */ return (SMB_Types[prot_index]); } else { /* Search through SMB_Prots looking for a match */ for (i = 0; SMB_Prots[i] != NULL; i++) { if (strcmp(dialects[prot_index], SMB_Prots[i]) == 0) { /* A match */ return (SMB_Types[i]); } } /* If we got here, then we are in trouble, because the protocol was not */ /* One we understand ... */ return (SMB_P_Unknown); }}/* Negotiate the protocol we will use from the list passed in Prots *//* we return the index of the accepted protocol in NegProt, -1 indicates *//* none acceptible, and our return value is 0 if ok, <0 if problems */intSMB_Negotiate(SMB_Handle_Type Con_Handle, char *Prots[]){ struct RFCNB_Pkt *pkt; int prots_len, i, pkt_len, prot, alloc_len; char *p; /* Figure out how long the prot list will be and allocate space for it */ prots_len = 0; for (i = 0; Prots[i] != NULL; i++) { prots_len = prots_len + strlen(Prots[i]) + 2; /* Account for null etc */ } /* 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 */ memset(SMB_Hdr(pkt), 0, 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, "%8s", (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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -