CN1375173A - 用于鉴别移动通信设备的方法和系统 - Google Patents
用于鉴别移动通信设备的方法和系统 Download PDFInfo
- Publication number
- CN1375173A CN1375173A CN00813031A CN00813031A CN1375173A CN 1375173 A CN1375173 A CN 1375173A CN 00813031 A CN00813031 A CN 00813031A CN 00813031 A CN00813031 A CN 00813031A CN 1375173 A CN1375173 A CN 1375173A
- Authority
- CN
- China
- Prior art keywords
- computer system
- code word
- code
- data
- message
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
Images
Classifications
-
- H—ELECTRICITY
- H04—ELECTRIC COMMUNICATION TECHNIQUE
- H04L—TRANSMISSION OF DIGITAL INFORMATION, e.g. TELEGRAPHIC COMMUNICATION
- H04L63/00—Network architectures or network communication protocols for network security
- H04L63/02—Network architectures or network communication protocols for network security for separating internal from external traffic, e.g. firewalls
- H04L63/029—Firewall traversal, e.g. tunnelling or, creating pinholes
-
- H—ELECTRICITY
- H04—ELECTRIC COMMUNICATION TECHNIQUE
- H04L—TRANSMISSION OF DIGITAL INFORMATION, e.g. TELEGRAPHIC COMMUNICATION
- H04L51/00—User-to-user messaging in packet-switching networks, transmitted according to store-and-forward or real-time protocols, e.g. e-mail
- H04L51/21—Monitoring or handling of messages
- H04L51/214—Monitoring or handling of messages using selective forwarding
-
- H—ELECTRICITY
- H04—ELECTRIC COMMUNICATION TECHNIQUE
- H04L—TRANSMISSION OF DIGITAL INFORMATION, e.g. TELEGRAPHIC COMMUNICATION
- H04L51/00—User-to-user messaging in packet-switching networks, transmitted according to store-and-forward or real-time protocols, e.g. e-mail
-
- H—ELECTRICITY
- H04—ELECTRIC COMMUNICATION TECHNIQUE
- H04W—WIRELESS COMMUNICATION NETWORKS
- H04W12/00—Security arrangements; Authentication; Protecting privacy or anonymity
- H04W12/06—Authentication
-
- H—ELECTRICITY
- H04—ELECTRIC COMMUNICATION TECHNIQUE
- H04L—TRANSMISSION OF DIGITAL INFORMATION, e.g. TELEGRAPHIC COMMUNICATION
- H04L51/00—User-to-user messaging in packet-switching networks, transmitted according to store-and-forward or real-time protocols, e.g. e-mail
- H04L51/58—Message adaptation for wireless communication
-
- H—ELECTRICITY
- H04—ELECTRIC COMMUNICATION TECHNIQUE
- H04W—WIRELESS COMMUNICATION NETWORKS
- H04W88/00—Devices specially adapted for wireless communication networks, e.g. terminals, base stations or access point devices
- H04W88/02—Terminal devices
Landscapes
- Engineering & Computer Science (AREA)
- Computer Networks & Wireless Communication (AREA)
- Signal Processing (AREA)
- Computer Security & Cryptography (AREA)
- Computer Hardware Design (AREA)
- Computing Systems (AREA)
- General Engineering & Computer Science (AREA)
- Information Transfer Between Computers (AREA)
- Computer And Data Communications (AREA)
- Data Exchanges In Wide-Area Networks (AREA)
- Mobile Radio Communication Systems (AREA)
Abstract
在用于鉴别移动通信设备(115)的方法和系统中,在计算机系统(101)中生成代码字,将该代码字传给所述设备(115)。在接收到代码字时,所述设备用该代码字自动地生成代码消息并将代码消息传给计算机系统。若计算机系统鉴别了代码字,则将数据从计算机系统传给所述设备。在一个最佳实施例中,所述设备用超本文传输协议(HTTP)或简单邮件传输协议(SMTP)来传输代码消息。这样做是有优点的,因为,防火墙设计成让使用这些协议的信息通过。因此,不会降低防火墙所提供的安全性。利用上述方法和系统,可获得多种不同类型的经鉴别的数据传输。例如,诸如电子邮件(E-mail)之类的自动传送数据、在安全的网络(诸如银行)上便利地注册、以及需要或希望鉴别用户的更多应用。
Description
技术领域
本发明涉及用于鉴别移动通信设备的方法和系统。具体地说,本发明涉及在计算机系统与移动通信设备之间传输数据的传输系统以及用于鉴别计算机系统的移动通信设备的方法。
发明背景和先有技术
在多种数据通信应用中,需要在位于防火墙内的计算机系统与位于防火墙外的移动客户之间进行数据传输。这种应用的一个实例是客户或用户连接到银行以便执行金融交易。在这种情况下,当然重要的是用户能鉴别自身以便提供保密的金融交易系统。这种应用的另一个实例是从公司将信息传给雇员。在这种情况下,重要的是按安全的方式将信息传递至正确的地址。
因此,重要的是提供一种鉴别客户的安全方法。但是,还希望鉴别过程是用户友好的。
还有,在国际专利申请WO97/08906中,说明了用于传输电子邮件的系统和主机结构。该结构使用了短文本消息(SMS),以便将电子邮件(E-mail)传给移动站。
发明概要
本发明的目的是提供用于鉴别移动远程通信设备并将数据从计算机系统传送至经鉴别的移动远程通信设备或从经鉴别的设备传送至计算机系统的方法和系统。
可以用能执行下列步骤的方法和系统来获得上述目的和其它目的:
(I)在计算机系统中生成代码字,将该代码字传送给所述设备;
(II)在所述设备中接收上述代码字;
(III)在所述设备中根据接收到的代码字生成代码消息,其中,按预定的方式执行上述生成过程;
(IV)将所述代码消息从上述设备传给计算机系统;
(V)用上述代码字检查代码消息;以及
(VI)若计算机系统验证了代码消息,则将数据从计算机系统传
送给所述设备。
在步骤(V)之前,计算机传输在鉴别过程中使用的信息(例如代码字和消息“你已获得邮件”),但是,所述设备尚不能访问计算机系统中的数据。最佳的是,计算机系统生成一个随机代码字。最佳的是,在计算机系统于步骤(I)中将代码字传送给所述设备时,计算机系统使用了该设备的预定地址。此外,在步骤(III)中,最好用所述设备的唯一加密密钥通过对接收到的代码进行加密而生成代码消息。如果验证了代码消息,即步骤(VI),则鉴别了所述设备的地址,以便进行数据传输。
在一个最佳实施例中,所述设备用超文本传输协议(HTTP)或简单邮件传输协议(SMTP)来传输代码消息。这样做是有优点的,因为,防火墙设计成让使用这些协议的业务流通过。换句话说,并未降低防火墙所提供的安全性。还有,最佳的是,计算机系统在步骤(VI)中将数据传给所述设备从其中发送出代码消息的那个地址,例如,计算机系统抽取出移动通信设备的该发送者地址并将数据传送给该地址。此地址不同于将代码字传送到的地址。
利用上述方法和系统,可获得多种不同类型的经鉴别的数据传输。例如,自动传送数据(诸如电子邮件(E-mail))、在安全的网络(诸如银行)上便利地注册、以及更多的其他应用,在这些应用中需要或希望在经过鉴别后进行传输。
使用本文所述的系统和方法还有助于从用户的角度进行鉴别。因此,在系统的客户方不需要一次口令生成器,因为,在系统的计算机系统方生成了随机代码字。
附图简述
以下参照附图用非限制性实例详细说明本发明,附图中
图1是用因特网自动传送E-mail或其它数据的系统的概略图;
图2是用分组数据网络自动传送E-mail或其它数据的系统的概略图;
图3是用于通过因特网连接自动鉴别设备的系统的概略图;
图4是说明在图1所示系统中鉴别移动通信设备和开始数据传输时执行的步骤的流程图;
图5a和5b是说明在图2所示系统中鉴别移动通信设备和开始数
据传输时执行的步骤的流程图;
图6是说明在图3所示系统中鉴别移动通信设备时执行的步骤的流程图。
最佳实施例的说明
在图1中,示出了用因特网连接自动传送E-mail或其它数据的系统的概略图。所述系统包括计算机系统101,该计算机系统又包括多种不同的计算机和其它设备。图1中的计算机系统包括电子邮件(E-mail)服务器103,它与计算机系统101的局域网(LAN)107相连。服务器103设置成处理计算机系统101中的电子邮件(E-mail)。计算机系统101还包括鉴别服务器105,它也与LAN107相连并与通信设备108相连,以便将消息传出计算机系统101。
整个计算机系统101例如位于防火墙109内。从防火墙109外使数据进入计算机系统101的唯一途径是通过防火墙109。防火墙109设置成仅让按HTTP或SMTP格式的数据通过。
移动通信设备115位于防火墙之外。防火墙与因特网111相连,因特网则又与多个因特网服务提供商(ISP)113相连。因特网服务提供商113提供一个接口,通过该接口诸如移动通信设备115之类的不同的设备可与因特网相连。
在图4中,流程图说明了在图1所示系统中鉴别移动通信设备和开始从计算机系统101至移动通信设备115的数据传输时执行的不同步骤。
首先,某种事件(诸如发送给设备115的用户的E-mail到达计算机系统101的E-mail服务器103)会触发创建从计算机系统101到设备115的经鉴别的传输,步骤401,也就是说,计算机系统101设置成能自动地传送数据,在这种情况下是传送E-mail,E-mail出现在计算机系统内并用于提供给一个当前在计算机系统101外部从而在防火墙109外部的客户。
系统101然后生成随机代码字,步骤403。该代码字是由鉴别服务器105生成的。例如通过传输一短消息服务(SMS)消息而用通信设备108将鉴别服务器105生成的代码字传给设备115,步骤405。鉴别服务器使用了用户的预定地址,在这种情况下是SMS号。设备155接收来自计算机系统101的代码字,步骤407。所述设备响应这种接收自动地连
接到因特网服务提供商(ISP)113,即步骤409。当设备115连接到ISP113时,该设备接收来自ISP113的因特网协议(IP)地址,步骤411。所述设备还根据接收到的代码字生成代码消息,步骤414。
当所述设备接收到了IP地址时,在该设备中创建E-mail服务器,步骤413。然后,将E-mail传给计算机系统的鉴别服务器105,步骤415。从设备115到鉴别服务器105的E-mail通过ISP113、因特网111、经由防火墙109并通过LAN107进行传送。
从设备115到鉴别服务器105的E-mail至少包括代码消息。该代码消息最好是通过用唯一的加密密钥对接收到的代码字进行加密而生成的。具体地说,通过连同加密密钥的一部分对代码字加密而生成代码消息。
在一个最佳实施例,用SMTP或HTTP协议来传输从所述设备到鉴别服务器105的E-mail,因为,防火墙109设计成仅能让这种数据业务流通过。因此,防火墙109可保持高度的安全性。最佳的是,使用SMTP协议,因为,这种协议仅需要使用一种用于连接的套接字(socket)。
因此,鉴别服务器接收来自所述设备的代码消息,步骤417。然后从接收到的E-mail中抽出代码字,如果代码字是加密的,则需对该代码字解密,步骤419。此后,检查所传输的代码字是否与抽取出的代码字相匹配,步骤421。
如果抽出的代码字与所传输的代码字不相匹配,则会话传束,步骤423。但是,在一个最佳实施例中,计算机系统101可设置成能在以后继续试图建立与设备115的经过鉴别的连接。
如果上述代码字在被抽出时与原本传给设备115的代码字相匹配,则鉴别服务器就会知道它是一个正确的设备。
鉴别服务器当前知道向哪里传输数据,在本例中,知道向哪里传输E-mail。因此,鉴别服务器105拷贝来自E-mail服务器的数据并用设备115的IP地址将E-mail传给该设备,步骤425。最好用设备115的唯一加密密钥对所传输的数据进行加密。
在图2中,示出了另一个用来自动传送E-mail或其它数据的系统,该系统使用了分组数据传输。图2所示的系统与图1所示的系统相类似。但是,使用了分组数据网络112,而不是用ISP113在计算机系统101与设备115之间传输数据。当然,可用因特网在计算机系统101
与分组数据网络112之间进行传输。
在图5a中,示出了说明在图2所示系统中鉴别移动通信设备时执行的步骤的流程图。图5中的流程图类似于图4的流程图。但是,通过分组数据网络112来进行从设备115到计算机系统101的传输。
还有,由于在这种情况下所述设备已经连接到移动网络,故在传输代码字时,可用分组数据网络将所述代码字传输给上述设备的预定地址。然后,可传输嵌在数据分组内的代码字。
在图5b中,示出了说明鉴别移动通信设备的另一种方式的流程图,它与以上连同图5a所述的方法相类似。
图5a的流程图与图5b的流程图之间的差别是,鉴别服务器抽取出代码字(图5a中的步骤419)并将其与前述代码字相比较,鉴别服务器抽取出代码消息(图5b中的步骤419)并将其与它自己利用与所述设备相同的代码消息生成算法生成的代码消息相比较。
因此,在接收到代码字时,所述设备通过将代码字用作代码消息生成算法的输入数据而生成代码消息,步骤414。然后,所述系统使用与上述设备相同的代码消息生成算法(步骤420),以便鉴别该设备。在接收到代码字(即步骤407)与传输E-mail(即步骤415)之间的时间间隔中,所述设备生成代码消息,步骤414。在生成代码字(即步骤403)与比较代码消息(即步骤421)之间的时间间隔中,鉴别服务器生成代码消息,步骤420。
在图3中,示出了通过因特网连接自动鉴别一个设备的系统的图。所使用的系统与图1或图2所示的系统相类似。图3所示的系统还包括金融交易服务器104,它与LAN107相连。
在图6中,示出了说明在图3所示系统中鉴别计算机系统101的设备115时执行的步骤的流程图。
因此,当设备115的用户因某种原因而要进行鉴别时,例如,他/她可能要利用安全连接在金融交易服务器104中进行金融交易时,用户就将E-mail从设备115传送给鉴别服务器105,以便请求被鉴别,步骤400。通过ISP113、因特网113、经由防火墙109并通过LAN107将包括诸如用户ID之类的标识用户的信息的E-mail传送给鉴别服务器105。
计算机系统101接收上述请求,步骤402。鉴别服务器105响应上
述请求生成代码字,具体地说,生成随机代码字,步骤403。然后,系统101例如通过传输短消息服务(SMS)消息而用通信设备108将代码字传送给设备115,步骤405。计算机系统将代码字发送给设备115的预定地址。计算机系统101利用从用户接收到的标识信息连同一个存储的地址列表来获得(预定的)地址。在另一个最佳实施例中,在因特网上将随机代码字传送给服务器或类似的装置,所述服务器则又将SMS传给设备115。
设备115接收来自计算机系统101的代码字,步骤407,并且生成代码消息。所述设备响应这种接收自动地将包括代码消息在内的第二E-mail传给计算机系统的鉴别服务器105,步骤415。通过ISP113、因特网111、经由防火墙109并通过LAN107传送从设备115到鉴别服务器105的第二E-mail。
应该注意,作为与连同图1和图4所述的鉴别过程的不同,设备115在传输包括代码消息的E-mail时不一定需要建立与因特网的新连接,因为,在步骤400中传输第一E-mail时业已建立了因特网连接。但是,当在所述设备于步骤407中接收到代码字时,如果做起来是有利的,则当然可以让所述设备第二次连接到因特网。
从设备115到鉴别服务器105的E-mail至少包括代码消息。最好用唯一的加密密钥来生成代码消息。具体地说,通过对代码字和加密密钥的一部分进行加密而生成代码消息。
在一最佳实施例中,用SMTP或HTTP协议传输从设备115到鉴别服务器105的E-mail,因为,防火墙109设计成仅让这种数据通过。因此,防火墙109可保持高度安全性。最佳的是使用SMTP协议,因为,这种协议仅需要使用一种用于连接的套接字。
因此,鉴别服务器接收来自所述设备的代码消息,步骤417。然后例如通过对代码消息加以抽取和解密而从接收到的E-mail中抽出代码字,步骤419。此后,检查所传输的代码字是否与抽取出的代码字相匹配,步骤421。
如果抽出的代码字与所传输的代码字不相匹配,则会话结束,步骤423。但是,在一个最佳实施例中,计算机系统101可设置成能将一消息返回给所述设备以便通知设备的用户:访问被拒绝,因此,用户可试图再度连接,如果他/她愿意这样做的话。
如果抽出的代码字与原本传给设备115的代码字相匹配,则鉴别服务器就会知道它是一个正确的设备。因此,客户可以开始在服务器104上进行交易,步骤425。
设备115可以是接收和发送数据的任何类型移动通信设备。因此,所述设备可以是移动电话、包括无线调制解调器的计算机或它们的组合,诸如包括集成移动电话的手持计算机。为了使设备115能适当地操作,所述设备必须装有能使该设备用上述方法进行通信的适当程序。能使该设备按上述方法进行操作所需的功能当然也可以用硬件来实现。也可以在计算机系统中提供用于该鉴别方法的软件或硬件支持。
除金融交易以外,还可在其它类型的交易中使用连同图3和6所述的系统。因此,可将上述系统用在多种需要快速而安全地鉴别设备的应用中。这种应用的实例是预订交易、订票交易、买卖货物等。
最后,在附录1-12中,示出了说明不同过程步骤的软件实现的计算机程序列表。因此,在附录l-6中,示出了计算机系统中某些过程步骤的C++语言的程序列表,例如,附录5-6中“lumpio”涉及编码和解码。在附录7-12中,示出了客户或设备中的某些过程步骤的列表,例如,在附图7-8中,在用功能“DoConnect”接收到SMS时,“pushnot”启动一个连接,附录11-12中的“client”用功能“lumpIO_fputs”和“lumpIO_fgets”进行解密和加密、用功能“send_file”发送邮件。
通过使用上述方法和系统,可以获得多种不同类型的经鉴别的数据传输。自动传送数据(诸如电子邮件(E-mail))、在安全的网络(诸如银行)上便利地注册、以及需要或希望在进行鉴别后进行传输的更多的其他应用。
/*附录1:pat_smtp.h*/ #ifndef lint static char*rcsid_notifier_h=″$Header$″; #endif #ifdef UNIX #define DEFAULT_LOG_FILE″/home/lmjm/pat_smtp/log″ #define DEFAULT_CONFIG_FILE″/home/janko/pat_smtp/pat_smtp.conf″ #define DEFAULT_ACCOUNTS_FILE″/home/janko/pat_smtp/accounts″ #define DEFAULT_QUEUE_DIR″/home/Janko/pat_smtp/queue″ #define DEFAULT_SERVER_VERSION″PAT Server 1.0beta″ #define MAX_ACCOUNTS 1000 #endif #ifdef WIN32 #define DEFAULT_LOG_FILE″c:/pat/logfile.txt″ #define DEFAULT_CONFIG_FILE″c:/pat/pat_smtp.conf″ #define DEFAULT_ACCOUNTS_FILE″c:/pat/accounts.txt″ #define DEFAULT_QUEUE_DIR″c:/pat/queue″ #define DEFAULT_SERVER_VERSION″PAT Server 1.0beta″ #define MAX_ACCOUNTS 1000 #endif #define CLIENT_DOM″ewi″ #define BIG_BUF 512 #define bool char #define true 1 #define false 0 extern bool smtp_listener; extern bool daemon; extern int verbose; extern char*config_file; extern char*queue_dir; extern char*server_version; extern char*program_name; extern int program_pid; void read_config_file();
/*附录 2:pat_smtp.cpp*/ /*SMTP收听者. *可在(UNIX)的inet下作为永久运行进程或用命令行运行。 * * *SMTP服务器要获得: *[[不需要步骤(a)-消息从EVO服务器进入我身后的适当位置 * *a)来自因特网的应发送给PAT客户(EPOC上)的“实时电子邮件” * -在这种情况下,应使要发送的邮件排队并使要发送给用户的包含 * 有用于对邮件进行鉴别的令牌的SMS。 * *]] * *b)来自PAT服务器的“PAT”电子邮件(在EPOC上)-始于 * 以下的起始“假”SMTP到来消息: * HELO * MAIL FROM:<epocclient_versionnumber@ewi> * RCPT TO:<patserver_versionnumber@ewi> * RCPT TO:<token_verification@ewi> * TURN * 用于鉴别PAT客户。 * 如果成功,则发送未决的电子邮件和‘TURN’, * 因此,一旦客户发送了用QUIT结束的任何电子邮件, * 则客户可按任何的未决电子邮件进行发送。 * *$Log$ */ #ifndef lint static char*rcsid=″$Header$″; #endif #include<stdio.h> #include<sys/types.h> #ifdef UNIX #include<unistd.h> #include<dirent.h> #include<pwd.h> #include<sys/time.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<netdb.h> #include<signal.h> #include<sys/stat.h> /*For getopt()*/ extern char*optarg; extern int optind #endif #ifdef WIN32 <!-- SIPO <DP n="9"> --> <dp n="d9"/> #include<stdlib.h> #include<io.h> #include<time.h> #include<process.h> #include<direct.h> #include<string.h> #inchude<sys/stat.h> #include<winsock2.h> #include″win_support.h″ #endif #include<string.h> #include<ctype.h> #include″pat_smtp.h″ #include″netio.h″ #include″keylib/keylib.h″ #include″log.h″ #include″base64.h″ #include″cryptsup.h″ #include″lumpIO.h″ #include″hex.h″ char*program_name=″pat_smtp″; int program_pid; bool smtp_listener=true; bool daemon=true; int verbose=2; u_short smtp_port=25; int max_listen_backlog=5; int pulse_time=5;/* 每5秒开始接收循环 */ int keep_looping=1; int smtp_timeout=120;/* 等待输入多长时间 */ int skip_authentication=1; #define MAX_DB_FIELDLEN 100 char user[MAX_DB_FIELDLEN], password[MAX_DB_FIELDLEN], evokey[MAX_DB_FIELDLEN], randnum[MAX_DB_FIELDLEN], dbtime[MAX_DB_FIELDLEN]; #define MAX_VERSION 100 char client_version[MAX_VERSION]; bool authenticated=false; void main(int argc,char**argv); void parse_args(int argc,char**argv); void become_daemon(); <!-- SIPO <DP n="10"> --> <dp n="d10"/> #ifdef UNIX void process_under_inetd(); char*get_my_login(); #endif void process_smtp(Sock io); bool process_state(int state,NET n,char*buf,char*addr); void process_queue_for_user(char*user,NET n); bool process_queue_file(char*qfilename,NET n); bool filename_matches(char*filename,char*user); void to_upper(char*str); int mail_rcpt_addr(char*buf,char*addr); #define TMP_IN 0 #define TMP_OUT 1 FILE*create_tmp(int where,char*tmp,char*user); int read_smtp_reply(NET n,char*buf,int bufsiz); void init_winsock(); void rename_in_tempfile(char*tmp_name); /* SMTP的应答是OK吗 */ #define REPLY_OK(r)((200<=(r))&&((r)<=299)) /* 表示服务器处于 */ #define ST_INIT 0 #define ST_HELO 1 #define ST_MAIL_CLIENT_VERS 2 #define ST_RCPT_SERVER_VERS 3 #define ST_RCPT_TOKEN 4 #define ST_MAIL_OUT 5 #define ST_RCPT_OUT 6 #define ST_DATA_OUT 7 #define ST_MAIL_IN 8 #define ST_RCPT_IN 9 #define ST_DATA_IN 10 void main(int argc,char**argv) { #ifdef WIN32 extern int_fmode; _fmode=_O_BINARY; #endif */ if(verbose){ netio_show(verbose); log_to_tty=1; } program_pid=getpid(); parse_args(argc,argv); #ifdef UNIX <!-- SIPO <DP n="11"> --> <dp n="d11"/> if(!smtp_listener){ to=get_my_login(); (void)queue_request(); exit(0); } if(daemon){ become_daemon(); exit(0); } process_under_inctd(); #endif #ifdef WIN32 become_daemon(); #endif } void parse_args(int argc,char**argv) { int c; char**nargv; #ifdef UNIX while((c=getopt(argc,argv,″avl:f:di:″))!=-1){ #endif/*UNIX*/ #ifdef WIN32 while(--argc>0){ char*arg=*++argv; char*optarg; c=*arg; if(c==′-′) c=arg[I]; else{ /* 不是参数-使nargv指针指向所有其它部分 */ nargv=argv; return; } switch(c){ case′l′: optarg=*argv++; } #endif/*WIN32*/ switch(c){ case′v′: verbose++; break; case′a′: skip_authentication=false;/* 必须鉴别用户 */ break; case′l′: log_file=optarg; <!-- SIPO <DP n="12"> --> <dp n="d12"/> if(*log_file!=′/′){ fprintf(stderr,″logfile name must begin with∧n″); exit(1); } break; case′f′: config_file=optarg; if(*config_file!=′/′){ fprintf(stderr,″config filename must begin with ∧n″); exit(I); } break; #ifdef UNIX case′d′: /*Run as a stand-alone daemon*/ smtp_listener=true; daemon=true; break; case′i′: /*Run under inetd*/ smtp_listener=true; daenon=false; break; #endif default: fprintf(stderr,″Usage:%s v[-l logfile][-f configfile][-d|i|-c From]\n″, program_name); fprintf(stderr,″-v verbose mode\n″); fprintf(stderr,″-l log to this file\n″); fprintf(stderr,″-f use this configuration file\n″); #ifdef UNIX fprintf(stderr,″-d run as stand-alone SMTP daemon\n″); fprintf(stderr,″-i run under inetd\n″); #endif fprintf(stderr,″-a authenticated\n″); exit(0); } } if(verbose) log_to_tty=1; } void become_daemon() { Sock sock,msgsock; struct sockaddr_in server; fd_set ready; struct timeval to; int on; read_config_file(); <!-- SIPO <DP n="13"> --> <dp n="d13"/> logit(INFO 1,″smtp daemon starting″); #ifdef WIN32 init_winsock(); #endif if((sock=socket(AF_INET,SOCK_STREAM,0))<0) logit(FATAL,″Cannot create stream socket″); server.sin_family=AF_INET; server.sin_addr.s_addr=htonl(INADDR_ANY); server.sin_port=htons(smtp_port); on=1; if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)(&on),sizeof(on))<0) logit(WARNING,″Cannot turn on SO_REUSEADDR″); if(bind(sock,(struct sockaddr*)&server,sizeof(server))<0) logit(FATAL,″Cannot bind to SMTP port%d″,smtp_port); listen(sock,max_listen_backlog); while(keep_looping){ logit(INFO,″loop waiting for SMTP connections″); FD_ZERO(&ready); FD_SET(sock,&ready); to.tv_sec=pulse_time; to.tv_usec=0; if(select(sock+1,&ready,0,0,&to)<0){ logit(WARNING,″select error″); continue; } if(FD_ISSET(sock,&ready)){ if((msgsock=accept(sock,(struct sockaddr*)0,(int*)0))<0) logit(WARNING,″failed to accept″); process_smtp(msgsock); } } } void process_smtp(Sock io) { NET n; int state=ST INIT; char buf[BIG_BUF]; char tmp1[BIG_BUF]; char tmp2[BIG_BUF]; char rcpt_to[BIG_BUF]; char mail_from[BIG_BUF]; char tmp_name[BIG_BUF]; FILE*tmp_f; <!-- SIPO <DP n="14"> --> <dp n="d14"/> struct sockaddr_in remote_addr; int addrlen=sizeof(remote_addr); struct hostent*hp; char remote_host[BIG_BUF]; logit(INFO,″process_smtp″); /* 找出谁呼叫我 */ if(getpeername(io,(struct sockaddr*)&remote_addr,&addrlen)<0){ logit(WARNING,″Cannot find remote host details″); strcpy(remote_host,″unknown″); } else{ hp=gethostbyaddr((char*)&(rsmote_addr.sin_addr), sizeof(struct in_addr),AF_INET); if(hp) (void)strncpy(remote_host,hp->h_name,sizeof(remote_host)); else (void)stmcpy(remote_host,inet_ntoa(remote_addr.sin_addr), sizeof(remote_host)); } logit(INFO 1,″process_smtp from%s″,&remote_host[0]); if((n=nopen(io))<0) logit(FATAL,″cannot use connection for smtp traffic″); /*Talk SMTP with the remote client*/ nprintf(n,″220 ME PAT_SMTP\r\n″); while(true){ bool rcpt_to_cmd,mail_from_cmd; rcpt_to_cmd=mail_from_cmd=false; if(timed_read_line(n,buf,sizeof(buf),smtp_timeout)<0) break; tmp1[0]=tmp2[0]=′\0′; sscanf(buf,″%[^\r\n]%*[\t]%[^\n\r]″,tmp1,tmp2); to_upper(tmp1); logit(INFO,″cmd:%s″,tmp1); if(strcmp(tmp1,″HELP″)==0){ nptintf(n,″214-Commands supported:\r\n″); nprintf(n,″213 HELO MAIL RCPT DATA TURN QUIT HELP\r\n″); continue; } else if(strcmp(tmp1,″HELO″)=0){ state=ST_HELO; if(!process_state(state,n,buf,″″)) break; continue; <!-- SIPO <DP n="15"> --> <dp n="d15"/> } else if(strcmp(tmp1,″MAIL″)==0){ if(!mail_rcpt_addr(buf,mail_from)){ nprintf(n,″500 Bad MAIL command\r\n″); continue; } if(state=ST_HELO) state=ST_MAIL_CLIENT_VERS; else if(state==ST_MAIL_IN){ state=ST_MAIL_IN;/*A tad redundant!*/ if((tmp_f=create_tmp(TMP_IN,tmp_name,user))== NULL){ nprintf(n,″500 Cannot create tmp files\r\n″); break; } } else{ nprintf(n,″501 Unexpected MAIL command\r\n″); continue; } if(!process_state(state,n,buf,mail_from)) break; continue; } else if(strcmp(tmp1,″RCPT″)==0){ if(!mail_rcpt_addr(buf,rcpt_to)){ nprintf(n,″500 Bad RCPT command\r\n″); continue; } if(state==ST_MAIL_CLIENT_VERS) state=ST_RCPT_SERVER_VERS; else if(state==ST_RCPT_SERVFR_VERS) state=ST_RCPT_TOKEN; else if(state==ST_MAIL_IN){ state=ST_RCPT_IN; } else{ nprintf(n,″501 Unexpected RCPT command\r\n″); continue; } if(!process_state(state,n,buf,rcpt_to)) break; continue; } else if(strcmp(tmp1,″DATA″)==0){ bool bad_end=false; char*buf_save; state=ST_MAIL_IN;/* 此后等待更多的邮件 */ struct lumpIO*f=lumpIO_init(key,iv,tmp_f); nprintf(n,″354 Enter message,ending with\″.\″on a line by itself\r\n″); while(1){ <!-- SIPO <DP n="16"> --> <dp n="d16"/> if(timed_read_line(n,buf,sizeof(buf),smtp_timeout)<0){ bad_end=true; break; } if(strcmp(buf,″.\r\n″)==0) break; /*If the line is just′..′skip the first′.′*/ if(strcmp(buf,″..\r\n″)==0) buf_save=&buf[1]; else buf_save=buf; lumpIO_fputs(buf_save,f); } if(bad_end) break; fclose(tmp_f); rename_in_tempfile(tmp_name); nprintf(n,″250 OK\r\n″); continue; } else if(strcmp(tmp1,″TURN″)==0){ if(state==ST_RCPT_TOKEN){ srate=ST_MAIL_OUT; nprintf(n,″250 turning(sending mail to client)\r\n″); /* 若声明则到主程序的结尾 */; } else{ nprintf(n,″501 Unexpected TURN command\r\n″); continue; } } else if(strcmp(tmp1,″QUIT″)==0){ nprintf(n,″221 closing\r\n″); break; } else{ nprintf(n,″500 Command unrecognized\r\n″); continue; } if(state==ST_MAIL_OUT){ int reply; process_queue_for_user(user,n); state=ST_MAIL_IN; nprintf(n,″TURN\r\n″); if((reply=read_smtp_reply(n,buf,sizeof(buf)))<0) break; if(REPLY_OK(reply)){ continue; } /* 客户未将电子邮件发送给我! */ nprintf(n,″QUIT\r\n″); <!-- SIPO <DP n="17"> --> <dp n="d17"/> break; } } nprintf(n,″200 So long and thanks for all the fish.\r\n″); nclose(n); logit(INFO,″end of process_smtp″); } bool process_state(int state,NET n,char*buf,char*addr) { if(state==ST_HELO){ nprintf(n,″250 watcha!\r\n″); return true; } if(state==ST_MAIL_CLIENT_VERS){ strcpy(client_version,addr); authenticated=false; nprintf(n,″250 thanks for the client version:<%s>\r\n″,addr); return true; } if(state==ST_RCPT_SERVER_VERS){ nprintf(n,″250 thanks for the server version:<%s>\r\n″,addr); return true; } if(state==ST_RCPT_TOKEN){ char*at,*dom,*dot; char*lwidx64,*resp64; char idxbuf[100];/* 应是6字节-忽略第一个2 */ int idxlen; int idx;/*The decoded index value*/ char keyidx[10];/* idx的串版本 */ int handle; unsigned long keyindex; char EvoKey_tmp[100]; char RandomToken_tmp[100]; if(skip_authentication){ authenticated=true; strcpy(user,addr); nprintf(n,″250 NON-authenticated user:%s\r\n″,user); return true; } /*addr是:lwidx.resp64@ewi *lwidx是base64(index) *resp64是base64(encrypt(hash(random))) */ authenticated=false; strcpy(user,″--Not Yet Set--″); <!-- SIPO <DP n="18"> --> <dp n="d18"/> at=strchr(addr,′@′); if(!at){ nprintf(n,″550 bad token/address:no @\r\n″); return false; } dom=at+1; if(strcmp(dom,CLIENT_DOM)!=0){ nprintf(n,″550 bad client domain:%s\r\n″,dom); return false; } dot=strchr(addr,′.′); if(!dot){ nprintf(n,″550 bad token/address:no.\r\n″); return false; } lwidx64=addr; *dot=′\0′; resp64=dot+1; *at=′\0′; logit(INFO1,″got:lwidx64%s,resp64%s″, lwidx64,resp64); from64_init(); int used; if((idxlen=from64(lwidx64,strlen(lwidx64),(unsigned char*)idxbuf, &used))<0){ nprintf(n,″550 idx not base64\r\n″); return false; } if(idxlen!=6){ nprintf(n,″550 idxlen should be 6 is%d for%s\r\n″,idxlen,lwidx64 ); return false; } memcpy(&idx,&idxbuf[2],4); sprintf(keyidx,″%d″,idx); if(kbd_open_db()!=OK){ nprintf(n,″550 Cannot access db\r\n″); return false; } handle=keyindex=0;/* 当前未用 */ /* 注意:在数据库中: * *随机令牌在BASE64 <!-- SIPO <DP n="19"> --> <dp n="d19"/> *EvoKEY 在 HEX */ if(kbd_get_key(handle, keyindex, keyidx, user, password, EvoKey_tmp, RandomToken_tmp, dbtime)!=OK){ if(kbd_close_db()!=OK) nprintf(n,″550-Failure to close db\r\n″); nprintf(n,″550 Cannot find%d in db\r\n″,idx); return false; } if(kbd_close_db()!=OK){ nprintf(n,″550 Failure to close db\r\n″); return false; } logit(INFO1,″db:user%s,pass%s,evokey%s,random token%s″, user,password,EvoKey_tmp,RandomToken_tmp); fromhex(EvoKey_tmp,EvoKey); from64_init(); int Random Token_len;/*TODO:Check this gets the right value*/ if((Random Token_len=from64(RandomToken_tmp,strlen( RandomToken_tmp),(unsigned char*)RandomToken,&used))<0){ nprintf(n,″550 random token not base64\r\n″); return false; } /*将接收到的base64(E(hash(rnd)))转换成8位形式 */ from64_init(); if((HashToken_str_len=from64(resp64,strlen(resp64),HashToken_str, &used))<0){ nprintf(n,″550 response part not base64\r\n″); return false; } /* 生成DES密钥 */ GenerateKey(key,24); /* 生成DES初始化矢量 */ GenerateKey(iv,8); /* 对接收到的8位形式解密 */ ctx_3des ctx_dec; unsigned char plaintext[256]; InitKey(&ctx_dec,key,iv); Decrypt(&ctx_dec,plaintext,HashToken_str,16); <!-- SIPO <DP n="20"> --> <dp n="d20"/> /*对数据库检索随机数进行杂凑 */ Hash md5(SSH_HASH_MD5); md5.Add(RandomToken,16); memcpy(db_hash_rnd_str,md5.Digest(),16); /*将db入口的杂凑值与解密的EPOC杂凑rnd令牌相比较 */ int result=memcmp(db_hash_rnd_str,plaintext,16); logit(INFO1,″db_has_rnd_str%02x%02x…,plaintext%02x%02x…″, db_hash_rnd_str[0],db_hash_rnd_str[1], plaintext[0],plaintext[1]); if(result!=0){ nprintf(n,″550 Authentication FAILED!<%s>(idx%d)\r\n″,user, idx); return false; } nprintf(n,″250 authenticated user:<%s>(idx%d)\r\n″,user,idx); return true; } if(state==ST_MAIL_IN){ nprintf(n,″250 MAIL TO for inet:<%s>\r\n″,addr); return true; } if(state==ST_RCPT_IN){ nprintf(n,″250 RCPT TO for inet:<%s>\r\n″,addr); return true; } return true; } void process_queue_for_user(char*user,NET n) { bool found,failed; char here[BIG_BUF]; char qdir[BIG_BUF]; logit(INFO,″process_queue for%s″,user); if(getcwd(here,BIG_BUF)==NULL) logit(FATAL,″Cannot find my current directory″); sprintf(qdir,″%s/out″,queue_dir); if(chdir(qdir)<0) logit(FATAL,″Cannot chdir to%s″,qdir); do{ #ifdef UNIX DIR*d; <!-- SIPO <DP n="21"> --> <dp n="d21"/> struct dirent*dfile; found=false; failed=false; if((d=opendir(″.″))==NULL) logit(FATAL,″cannct open queue directory:%s″,qdir); while((dfile=readdir(d))!=NULL){ char*filename=dfile->d_name; if(filename_matches(filename,user)){ continue; logit(INFO,″Found j file:%s″,filename); if(!process_queue_file(filename,n)){ failed=true; break; } found=true; } closedir(d); #endif #ifdef WIN32 struct_finddata_tj_file; long hFile; found=false; failed=false; /* 找出当前目录中第一个j* 文件 */ if((hFile=_findfirst(″j*.*″,&j_file))!=-1I.)( if(filename_matches(j_file.name,user)){ logit(INFO,″Found j file:%s″,j_file.name); if(!process_queue_file(j_file.name,n)){ failed=true; break; } found=true; } /* 找出其余的j* 文件 */ while(_findhext(hFile,&j_file)==0&&!failed){ if(filename_matches(j_file.name,user)){ logit(INFO,″Found j file:%s″,j_file.name); if(!process_queue_file(j_file.name,n)){ failed=true; break; } found=true; } } } _findclose(hFile); #endif <!-- SIPO <DP n="22"> --> <dp n="d22"/> }while(found&&!failed); if(chdir(here)<0) logit(FATAL,″Cannot chdir to%s″,here); logit(INFO,″findished processing queue″); } /*j+用户+′.′+NNN*/ bool filename_matches(char*filename,char*user) { char tmp[100]; char*dot; strcpy(tmp,&filename[1]); dot=strchr(tmp,′.′); if(!dot) return false; *dot=′\0′; return strcmp(tmp,user)==0; } bool process_ueue_file(char*qfilename,NET n) { FILE*qf; char tmp[BIG_BUF]; int ret; bool eof_ok=false; logit(INFO,″process_queue_file:%s″,qfilename); logit(INFO,″Send MAIL FROM:<%s>″,server_version); nprintf(n,″MAIL FROM:<%s>\r\n″,server_version); ret=read_smtp_reply(n,tmp,sizeof(tmp)); if(!REPLY_OK(ret)){ logit(WARNING,″bad reply to MAIL FROM of%d″,ret); return false; } logit(INFO,″Send RCPT TO:<%s>″,client_version); nprintf(n,″RCPT TO:<%s>\r\n″,client_version); ret=read_smtp_reply(n,tmp,sizeof(tmp)); if(!REPLY_OK(ret)){ logit(WARNING,″bad reply to RCPT TO of%d″,ret); return false; } logit(INFO,″Send data from file:%s″,qfilename); if((qf=fopen(qfilename,″r″))==NULL) logit(FATAL,″Cannot open queue file:%s″,qfilename); <!-- SIPO <DP n="23"> --> <dp n="d23"/> logit(INFO,″DATA″); nprintf(n,″DATA\r\n″); logit(INFO,″Read reply to DATA″); ret=read_smtp_reply(n,tmp,sizeof(tmp)); if(!(300<=ret && ret<=399)){ logit(WARNING,″bad reply to DATA of%d″,ret); return false; } struct lumpIO*f=lumpIO_init(key,iv,qf); while(lumpIO_fgets((unsigned char*)&tmp[0],BIG_BUF,f)!=NULL){ #ifdef UNIX char*nl=strchr(tmp,′\n′); if(nl) strcpy(nl,″\r\n″); #endif #ifdef WIN32 char*nl=strchr(tmp,′\r′); if(nl && nl[1]!=′\n′) strcpy(nl,″\r\n″); #endif if(feof(qf)&&nl) eof_ok=true; if(strcmp(tmp,″.\r\n″)==0) strcpy(tmp,″..\r\n″); logit(INFO,″Send:%s″,tmp); nprintf(n,″%s″,tmp); } logit(INFO,″Send.″); if(eof_ok) nprintf(n,″.\r\n″); else nprintf(n,″\r\n.\r\n″); fclose(qf); logit(INFO,″Read reply to email″); ret=read_smtp_reply(n,tmp,sizeof(tmp)); if(!REPLY_OK(ret)){ logit(WARNING,″bad reply to email of%d″,ret); return false; } /*一旦完成工作,就从j*改名至d**/ strcpy(tmp,qfilename); *tmp=′d′; logit(INFO,″Rename old qfile from%s to%s″,qfilename,tmp); if(rename(qfilename,tmp)<0) logit(FATAL,″cannot rename%s to%s″,qfilename,tmp); return true; } <!-- SIPO <DP n="24"> --> <dp n="d24"/> /*检查buf是否是′某个cmd:<地址>′,由该地址填写addr。 *若一切OK则返回true,否则返回false */ int mail_rcpt_addr(char*buf,char*addr) { char*gt; int len; char*a=strchr(buf,′:′); if(!a) return false; a++;/*跳过 :*/ if(*a!=′<′) return false; /*转至>*/ gt=strchr(++a,′>′); if(!gt) return false; len=gt-a; strncpy(addr,a,len); addr[len]=′\0′; return true; } #ifdef UNIX void process_under_inetd() { /*UNTESTED*/ logit(INFO1,″process_under_inetd″); process_smtp(0); } char*get_my_login() { int uid=getuid(); struct paswd*pw=getpwuid(uid); if(pw==NULL){ logit(FATAL,″cannot find login name for uid:%d″,uid); } return pw->pw name; } #endif void to_upper(char*str) { int c; while((c=*str)){ if(islower(c)) c=toupper(c); *str++=c; <!-- SIPO <DP n="25"> --> <dp n="d25"/> } } FILE*create_tmp(int where,char*tmp,char*user) { char*ret; if(where==TMP_IN) sprintf(tmp,″%s/in/t%s.XXXXXX″,queuc_dir,user); else sprintf(tmp,″%s/out/t%s.XXXXXX″,queue_dir,user); if((ret=mktemp(tmp))==NULL) return NULL; return fopen(tmp,″w″); } int read_smtp_reply(NET n,char*buf,int bufsiz) { int ret; if(timed_read_line(n,buf,bufsiz,smtp_timeout)<0) return-l; logit(INFO,″read reply:%s″,buf); sscanf(buf,″%d″,&ret); logit(INFO,″read reply value:%d″,ret); return ret; } #ifdef WIN32 void init_winsock() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested=MAKEWORD(2,0); err=WSAStartup(wVersionRequested,&wsaData); if(err!=0) logit(FATAL,″Cannot find usable winsock DLL″); /* 确认WinSock DLL支持2.0。 */ /* 注意,若DLL支持除2.0以外还支持 */ /* 2.0以上版本,则在wVersion中 */ /* 仍返回2.0.因为,该版本是我们请求 */ /* 的版本. */ <!-- SIPO <DP n="26"> --> <dp n="d26"/> if(LOBYTE(wsaData.wVersion)!=2‖ HIBYTE(wsaData.wVersion)!=0){ WSACleanup(); logit(FATAL,″Cannot find usable winsock DLL-wrong version″); return; } /* WinSock DLL是可接受的,继续进行 */ } #endif /*一旦作业完成就将其改名,即从 *../in/t<user>.<uniq>改为.../in/j.<user>.<NNN>.. */ void rename_in_tempfile(char*tmp_name) { char*sl,*num; char buf[BIG_BUF]; struct stat sb; int n; strcpy(buf,tmp_name); sl=strrchr(buf,′/′); sl[1]=′j′; num=strchr(buf,′.′); num++; for(n=0;n<=999;n++){ sprintf(num,″%03d″,n); if(stat(buf,&sb)<0) /* 找出未用的文件名! */ break; } if(n>=999) logit(FATAL,″No free filenames!″); logit(INFO,″Rename incoming from%s to%s″,tmp_name,buf); if(rename(tmp_name,buf)<0) logit(FATAL,″No free filenames!″); }
/*附录 3:cryptsup.h*/ #ifndef CRYPTSUP_H #define CRYPTSUP_H #include″patparts/hash.h″ #include″patparts/getput.h″ struct ctx_3des { des_key_schedule ks1,ks2,ks3; unsigned char iv[8]; }; void InitKey(ctx_3des*ctx,unsigned char*key,unsigned char*iv); void Encrypt(ctx_3des*ctx,unsigned char*dest,unsigned char*src,int len); void Decrypt(ctx_3des*ctx,unsigned char*dest,unsigned char*src,int len); void GenerateKey(unsigned char*key,int keylen); int des_ede_encrypt(unsigned char*input,unsigned char*output,des_key_scedule ks1, des_key_schedule ks2,des_key_schedule ks3,int encrypt); void des3_cbc(unsigned char*dest, const unsigned char*src,int len, des_key_schedule ks1,des_key_schedule ks2, des_key_schedule ks3,unsigned char*iv, int for_encryption); extern unsigned char RandomToken[16]; extern unsigned char db_hash_rnd_str[16]; extern unsigned char HashToken_str[16]; extern int HashToken_str_len; extern unsigned char EvoKey[8]; extern unsigned char key[24],iv[8]; #endif
/*附录 4:cryptsup.cpp*/ #include<memory.h> #include″log.h″ #include″hex.h″ #include″cryptsup.h″ #include″patparts/hash.h″ unsigned char RandomToken[16]; unsigned char db_hash_rnd_str[16]; unsigned char HashToken_str[16]; int HashToken_str_len; unsigned char EvoKey[8]; unsigned char key[24],iv[8]; void GenerateKey(unsigned char*key,int keylen) { Hash md5(SSH_HASH_MD5); unsigned char*k=key; int klen=keylen; dumphex(″GenerateKey:EvoKey″,EvoKey,sizeof(EvoKey)); logit(INFO,″ch%04x,keylen%d″,ch,keylen); dumphex(″RandomToken″,RandomToken,sizeof(RandomToken)); md5.Add(EvoKey,sizeof(EvoKey)); md5.Add(RandomToken,sizeof(RandomToken)); memcpy(key,md5.Digest(),(keylen>=16)?16:keylen); dumphex(″key so far″,key,keylen); for(int len=16;(keylen-=16)>0;len+=16){ md5.Init(SSH_HASH_MD5); md5.Add(Evokey,sizeof(EvoKey)); md5.Add(key,len); memcpy(key+len,md5.Digest(),(keylen>=16)?16:keylen); } dumphex(″=>key:″,key,klen); } int des_ede_encrypt(unsigned char*input,unsigned char*output,des_key_schedule ks1, des_key_schedule ks2,des_key_schedule ks3,int encrypt) { unsigned long 11[2]; 11[0]=GetLong_Little(input); <!-- SIPO <DP n="29"> --> <dp n="d29"/> 11[1]=GetLong_Little(input+4); des_encrypt(11,11,ks1,encrypt); des_encrypt(11,11,ks2,!encrypt); des_encrypt(11,11,ks3,encrypt); PutLong_Little(output,11[0]); PutLong_Little(output+4,11[1]); return(0); } void des3_cbc(unsigned char*dest, const unsigned char*src,int len, des_key_schedule ks1,des_key_schedule ks2, des_key_schedule ks3,unsigned char*iv, int for_encryption) { int n; if(for_encryption){ while(len>0){ unsigned char input[8]; for(n=0;n<8;++n) input[n]=src[n]^iv[n]; des_ede_encrypt(input,iv,ks1,ks2,ks3,1); memcpy(dest,iv,8); src+=8; dest+=8; len-=8; } } else{ while(len>0){ unsigned char output[8]; des_ede_encrypt((unsigned char*)src,output,ks1,ks2,ks3,0); for(n=0;n<8;++n) dest[n]=output[n]^iv[n]; memcpy(iv,src,8); src+=8; dest+=8; len-=8; } } } void lnitKey(ctx_3des*ctx,unsigned char*key,unsigned char*iv) { des_set_key((des_cblock*)key,ctx->ks1); des_set_key((des_cblock*)(key+8),ctx->ks2); des_set_key((des_cblock*)(key+16),ctx->ks3); memcpy(ctx->iv,iv,8); } <!-- SIPO <DP n="30"> --> <dp n="d30"/> void Encrypt{ctx_3des*ctx,unsigned char*dest,unsigned char*src,int len) { des3_cbc(dest,src,len,ctx->ks1,ctx->ks2,ctx->ks3,ctx->iv,1); } void Decrypt(ctx_3des*ctx,unsigned char*dest,unsigned char*src,int len) { des3_cbc(dest,src,len,ctx->ks3,ctx->ks2,ctx->ks1,ctx->iv,0); }
/*附录 5:lumpio.h/ #ifndef lumpIO_H #define lumpIO_H #ifndef lint static char*rcsid_lumpIO_h=″$Header$″; #endif #include″cryptsup.h″ struct lumpIO { FILE*f; unsigned char key[24],iv[8]; ctx_3des ctx_dec; }; struct lumpIO*lumpIO_init(unsigned char key[24],unsigned char iv[8],FILE*f); unsigned char*lumpIO_fgets(unsigned char*buf,int buflen,struct lumpIO*lio); int lumpIO_fputs(char*string,struct lumpIO*lio); #endif
/*附录 6:lumpio.cpp*/ #ifndef lint static char*rcsid=″$Header$″; #endif #include<stdio.h> #include<memory.h> #include<string.h> #include″lumpIO.h″ #include″base64.h″ #include″log.h″ struct lumpIO lumpIO; struct lumpIO* lumpIO_init(unsigned char key[24],unsigned char iv[8],FILE*f) { memcpy(lumpIO.key,key,24); memcpy(lumpIO.iv,iv,8); /* 生成DES密钥 */ GenerateKey(lumpIO.key,24); /* 生成DES初始化矢量 */ GenerateKey(lumpIO.iv,8); InitKey(&lumpIO.ctx_dec,lumpIO.key,lumpIO.iv); lumpIO.f=f; return&lumpIO; } /* 从文件中读出数据并对数据作加密和base64编码。 * 加密例程仅能处理是8 AND 6的倍数的数据, * 因此,数据块中的fread()对数据加密和编码。 * 但是,由于可能部分地填充最后的数据块, * 故必须传送数据的长度,最好传送所有块的长度, * 所以,发送的数据是长度未用的72字节数据=74字节。 */ #define LUMP_LENGTH 74 #define LUMP_DATA_LEN(LUMP_LENGTH-2) struct lump { char length; char unused; unsigned char data[LUMP_DATA_LEN]; }; unsigned char*lumpIO_fgets(unsigned char*buf,int buflen,struct lumpIO*lio) { <!-- SIPO <DP n="33"> --> <dp n="d33"/> struct lump 1; unsigned char tmp_in[LUMP_DATA_LEN]; if(buflen<LUMP_DATA_LEN) return NULL; if(sizeof(lump)!=LUMP_LENGTH) logit(FATAL,″sizeof(lump)=%d!=LUMP_LENGTH=%d″, sizeof(lump),LUMP_LENGTH); FILE*f=lio->f; if(feof(f)‖ferror(f)) return NULL; int in=fread(&tmp_in[0],sizeof(char),LUMP_DATA_LEN,f); if(in<0) return NULL; logit(INFO,″fread%d bytes<<%*.*s>>″,in,in,in,&tmp_in[0]); l.length=(char)in; l.unused=0; Encrypt(&lio->ctx_dec,&l.data[0],&tmp_in[0],LUMP_DATA_LEN); to64((unsigned char*)&l,LUMP_LENGTH,buf); strcat((char*)buf,″\r\n″); return buf; } /* 取base64,加密的串,在将其写至文件之前进行非base64和 * 非加密处理。 * 基本行在被写成lumpIO_fgets时是一集总块。 */ int lumpIO_fputs(char*str,struct lumpIO*lio) { struct lump 1; unsigned char tmp_out[LUMP_DATA_LEN]; FILE*f=lio->f; if(feof(f)‖ferror(f)) return EOF; if(sizeof(lump)!=LUMP_LENGTH) logit(FATAL,″sizeof(lump)=%d!=LUMP_LENGTH=%d″, sizeof(lump),LUMP_LENGTH); from64_init(); int used,from; if((from=from64(str,strlen(str),&tmp_out[0],&used))<0) return-1; <!-- SIPO <DP n="34"> --> <dp n="d34"/> l.length=tmp_out[0]; Decrypt(&lio->ctx_dec,(unsigned char*)&l.data[0],&tmp_out[2], LUMP_DATA_LEN); int ret=fwrite(&l.data[0],sizeof(char),l.length,f); if(ret<0) return EOF; return ret; }
/*附录 7:pushnot.h*/ #ifndef_FLOAT_H_ #define_FLOAT_H_ #include″sms.h″ #include″smsstat.h″ #include<s32file.h> #include<coecntrl.h> #include<coeccntx.h> #include<eikappui.h> #include<eikapp.h> #include<eikdoc.h> #include<eikmover.h> #define PUSH_ID 0x1000508 #define KEEP_ON 1 //发送时使Psion′s自动化无效 switch off //各种连接状态 enum(CONNECT0,CONNECT1,CONNECT2,CONNECT3,CONNECT4}; class CGuiViewColumnListBoxControl; ///////////////////////////////////////////////////////////////////////////////////// // //类 CFloatCloseAppUi // //激活AppUi退出功能的“关闭”钮 // class CFloatAppUi; class CFloatCloseAppUi:public CCoeControl { public: CFloatCloseAppUi(CFloatAppUi*anAppUi); public://from CCoeControl void Draw(const TRect&aRect)const; void HandlePointerEventL(const TPointerEvent&aPointerEvent); private: CFloatAppUi*iControllingAppUi; }; enum{EFloatTitleHeight=21}; enum{EFloatMargin=10}; enum{EFloatWidth=210,EFloatHeight=[10};//按象素的初始显示尺寸 <!-- SIPO <DP n="36"> --> <dp n="d36"/> enum { EFloatWindowWidth=EFloatWidth+2*EFloatMargin, EFloatWindowHeight=EFloatHeight+2*EFloatMargin+EFloatTitleHeight, }; enum{EFloatBorderWidth=1}; ///////////////////////////////////////////////////////////////////////////////////// // //类 CFloatControl // //用于 CFloatWindow的控制类。 // ///////////////////////////////////////////////////////////////////////////////////// // //类 CFloatAppUi // //浮动应用的用户接口 class CNewControl; class CNotifier; class CFloatAppUi:public CEikAppUi { public: CFloatAppUi(); ~CFloatAppUi(); void ConstructL(); void FloatExit(); void DoTest(); void AddLine(char*Text); void AddLine(TDesC8&Text); TInt TextWidth(char*Text); CNewControl*GetControl(){return iNewControl;}; private: void HandleCommandL(TInt aCommand); private://提供功能 void CmdDlgRateL(); void CmdDlgFileSaveAsL(); void FloatIn(); void FloatOut(); void SetWindowSizeL(TSize); TSize WindowSize(); public: RFs fileserver; TInt ConnectionStatus; CSMSStats PhoneStat; ESMSUtil*SMSUtils; CPeriodic*SmsTimer; private: <!-- SIPO <DP n="37"> --> <dp n="d37"/> CNewControl*iNewControl; TTimelntervalMicroSeconds32 iInterval; RThread SMSThread; CGuiViewColumnListBoxControl*iColumnView; private: enum{ EFloatFactorDelta=200, EWindowSizeDelta=2 }; }; ///////////////////////////////////////////////////////////////////////////////////// // // 类 CFloatDocument // class CFloatDocument:public CEikDocument { public: CFloatDocument(CEikApplication&aApp):CEikDocument(aApp){ } private://from CApaDocument CEikAppUi*CreateAppUiL(); }; ///////////////////////////////////////////////////////////////////////////////////// // // 类 CFloatApplication // class CFloatApplication:public CEikApplication { private: CApaDocument*CreateDocumentL(); TUid AppDllUid()const; }; const TUid KUidFloatApp={PUSH_ID}; enum {ENewTitleHeight=21}; enum {ENewMargin=5}; enum {ENewWidth=210,ENewHeight=60};//initial size of display in pixels enum { ENewWindowWidth=ENewWidth+2*ENewMargin, ENewWindowHeight=ENewHeight+2*ENewMargin+ENewTitleHeight, }; enum {ENewBorderWidth=1}; <!-- SIPO <DP n="38"> --> <dp n="d38"/> ///////////////////////////////////////////////////////////////////////////////////// // // 类 CNewWindow // class CNewWindow:public CCoeControl { enum{ETextBoxWidth=180}; public: ~CNewWindow(); CNewWindow(); void ConstructL(); void SetActive(TBool aActive); TBool Active()const; TSize MinimumSize(); private://overridden void Draw(corst TRect&aRect)const; void HandlePointerEventL(const TPointerEvent&aPointerEvent); protected: void SizeChangedL(); private: TBuf<80>iText; TBool iActive; TRect iScreenRect; CFbsBitmap*iBitmap; }; ///////////////////////////////////////////////////////////////////////////////////// // // 类 CNewControl // // 用于 CNewWindow的控制类。 // class CNewControl:public CCoeControl,public MCoeControlObserver { public: public://From CCoeControl CNewControl(CFloatAppUi*anAppUi); ~CNewControl(); void ConstructL(); void SizeChangedL(); virtual TInt CountComponentControls()const; virtual CCoeControl*ComponentControl(TInt aIndex)const; virtual TKeyResponse OfferKeyEvertL(const TKeyEvent&aKeyEvent,TEventCode aType); virtual TSize MinimumSize(); void HandleControlEventL(CCoeControl*aControl,TCoeEvent aEventType); CEikCommandButton*NewButton(const TDesC8&text); inline CNewWindow*GetWindow(){return iNewWindow;}; <!-- SIPO <DP n="39"> --> <dp n="d39"/> private: void Draw(const TRect&aRect)const; private: TSize iWindowSize; TRect iNewRect; CEikMover* iMover; CEikCommandButton*iTestButton; CNewWindow* iNewWindow; CFloatAppUi*iParentAppUi; CFloatCloseAppUi* iClose; }; #define POLL_PHONE_RATE 300000//number of microseconds between polling phone TInt PollPhone(TAny*APtr); //周期性计时器的回调函数。 #endif
/*附录 8:pushnot.cpp*/ #include<eikchlst.h> #include<eikopbut.h> #include<eikdlgtb.h> #include<eikmenu.hrh> #include<eikcmds.hrh> #include<eikchlst.hrh> #include<eikdialg.h> #include<coecntrl.h> #include<eikappui.h> #include<eikdoc.h> #include<eikenv.h> #include<eikdef.h> #include<eikapp.h> #include<eikmover.h> #include<eikrubtl.h> #include<badesca.h> #include<basched.h> #include<barsread.h> #include<e32hal.h> #include<e32std.h> #include<e32base.h> #include<frmframe.h> #include<eikcfdlg.h> #include<eikon.rsg> #include<eikcmbut.h> #include<eiklabel.h> #include<eikpgsel.h> #include″pushnot.hrh″ #include″pushnot.h″ #include<pushnot.rsg> #include″brnaps.h″ #include″euclsv.h″ #include″socket.h″ #include″ncteserv.h″ #include″iobox.h″ #include″smsutil.h″ #include″crypt.h″ #include″client.h″ #include″listwin.h″ #define PAT_IP_ADDRESS((195*0x1000000)+(50*0x10000)+(91*0x100)+208) void DoConnect(CFloatAppUi*ParentAppUi); TInt ThreadFunction(TAny*anArg); void StartThread(CFloatAppUi*ParentAppUi,RThread*thread); void CFloatAppUi∷AddLine(TDesC8&Text) { char*Txt=(char*)Text.Ptr(); <!-- SIPO <DP n="41"> --> <dp n="d41"/> Txt[Text.Length()]=0; AddLine(Txt); // iColumnView->GetListArray()->AppendL(Buffer); // iColumnView->SetCurrentItem(9000); // iColumnView->RedrawL(); } #define IsPunct(a)((a==′′)‖(a==′,′)‖(a==′.′) ‖(a==′?′)‖(a==′!′)‖(a==′:′)‖(a==′;′)) TInt CFloatAppUi∷TextWidth(char*Text) { TPtrC8*Buffer=new TPtrC8((TUint8*)Text); TInt width=iEikonEnv->Static()->NormalFont()->TextWidthInPixels(*Buffer); delete Buffer; return(width); } #define SCREEN_WIDTH 380 void CFloatAppUi∷AddLine(char*Text) { char KeepChar; TInt TextPtr=0,BestSoFar=0; Tlnt width=TextWidth(Text); if(width>SCREEN_WIDTH) { do { //find end of string or punctuation // while((Text[TextPtr]!=0)&&(!(IsPunct(Text[TextPtr])))) // { // TextPtr++; // } //exit loop if end found if(Text[TextPtr]==0)break; KeepChar=Text[TextPtr]; Text[TextPtr]=0; //and find out it′s width now width=TextWidth(Text); <!-- SIPO <DP n="42"> --> <dp n="d42"/> Text[TextPtr]=KeepChar; //如与屏幕相称,则保持其位置 if(width<SCREEN_WIDTH)BestSoFar=TextPtr; TextPtr++; }while(width<SCREEN_WIDTH);//but keep looking until we wrap if(BestSoFar!=0) { KeepChar=Text[BestSoFar]; Text[BestSoFar]=0; TBufC8<512>Buffer((const unsigned char*)Text); iColumnView->GetListArray()->AppendL(Buffer); iColumnView->RedrawL(); Text[BestSoFar]=KeepChar; AddLine(&Text[BestSoFar]); return; } } TBufC8<512>Buffer((const unsigned char*)Text); iColumnView->GetListArray()->AppendL(Buffer); iColumnView->SetCurrentItem(9000); iColumnView->RedrawL(); } //RSemaphore信号 ; #pragma data_seg(″.E32_UID″) _WINS_UID(0x10000079,KAPPUidValue,PUSH_ID) #pragma data_seg() #define WANT_WINDOW #define MAIL_W 50 #define MAIL_H 53 #define BYTES_W 50 #define BYTES_H 53 #define STAT_W 100 #define STAT_H 35 #define PHONE_W (EFloatWidth-STAT_W-4) #define PHONE_H 35 #define SPACER 4 //拼图块与邮箱间的间隔 <!-- SIPO <DP n="43"> --> <dp n="d43"/> #define TILES_WIDTH (EFloatWidth-(MAIL_W+BYTES_W+2*SPACER)) //x position of left tile when broken apart #define X_LEFT ((EFloatWindowWidth-TILES_WIDTH)/2) //x position of centre tile at all times #define X_CENTRE((EFloatWindowWidth-CentreBMWidth)/2) //x psoition of right tile when broken apart #define X_RIGHT ((EFloatWindowWidth+TILES_WIDTH)/2-RightBMWidth) //x position of left tile when closed #define X_LEFT3 (X_CENTRE-LeftBMWidth+15) //x position of left tile when closing #define X_LEFT2 (X_LEFT+(X_LEFT3-X_LEFT)/2) //x position of right tile when closed #define X_RIGHT3 (X_CENTRE+69) //x position of right tile when closing #define X_RIGHT2 (X_RIGHT+(X_RIGHT3-X_RIGHT)/2) #define PHONE_BAR_W (PHONE_W-74)/2 #define BATTERY_BAR_W (PHONE_W-74)/2 #define SMALL_PIECE 4 #define GAP 2 #define BM_X MAIL_W+5 #define BLOCK_HEIGHT 8 #define BLOCK_WIDTH 6 #define BLOCK_SPACE 2 #define BUTTON TOP MARGIN 6 //标题与按钮间的边缘 #define BUTTON_BOTTOM_MARGIN 0 //按钮间的边缘 window #define TOTAL_MARGIN (BUTTON_TOP_MARGIN+BUTTON_BOTTOM_MARGIN) #define KFloatDefaultPath_L(″C:\\″) int Wait(TTimeIntervalMicroSeconds32 Delay); int Wait(TTimeIntervalMicroSeconds32 Delay) { RTimer timer; TRequestStatus TStat; timer.CreateLocal(); timer.After(TStat,Delay); User∷WaitForRequest(TStat); timer.Close(); return(TRUE); <!-- SIPO <DP n="44"> --> <dp n="d44"/> } ///////////////////////////////////////////////////////////////////////////////////// // // 类 CFloatCloseAppUi // //激活AppUi退出功能的“关闭″钮 // CFloatCloseAppUi∷CFloatCloseAppUi(CFloatAppUi*anAppUi) :iControllingAppUi(anAppUi) { _DECLARE_NAME(_S(″CFloatCloseAppUi″)); SetNonFocusing(); } void CFloatCloseAppUi∷Draw(const TRect&/*aRect*/)const { CWindowGc&gc=SystemGc(); //draws the surrounding box TRect rect=Rect(); gc.DrawRect(rect); TPoint pos=Position(); gc.MoveTo(TPoint(pos.iX,rect.Size().iHeight)); gc.DrawLineBy(TPoint(rect.Size()-iWidth,-rect.Size().iHeight)); gc.MoveBy(TPoint(0,rect.Size().iHeight)); gc.DrawLineBy(TPoint(-rect.Size().iWidth,-rect.Size().iHeight)); } void CFloatCloseAppUi∷HandlePointerEventL(const TPointerEvent&aPointerEvent) { if(aPointerEvent.iType==TPointerEvent∷EButtonlDown) iControllingAppUi->FloatExit(); } ///////////////////////////////////////////////////////////////////////////////////// // // 类 CFloatAppUi // CFloatAppUi∷CFloatAppUi() { // iInterval=20*100000; } <!-- SIPO <DP n="45"> --> <dp n="d45"/> void CFloatAppUi∷DoTest() { /* HBufC*tmp=HBufC∷New(256); PatClient Pat; CWSocket*Socket; *tmp=(_L(″Hello″)); Pat.timed_read_line(Socket,tmp->Des(),10); delete tmp;*/ // PatClient Pat; // Pat.GenFCount(fileserver); } void CFloatAppUi∷ConstruotL() { User∷LeaveIfError(fileserver.Connect()); // DoTest(); SMSUtils=new ESMSUtil(&this->PhoneStat); #ifndef_WINS_ SMSUtils->OpenPort(); //打开红外并配置 #endif BaseConstructL(); iColumnView=new(ELeave)CGuiViewColunnListBoxControl(this); iColumnView->ConstructL(ClientRect()); AddToStackL(iColumnView); iColumnView->ActivateL(); iColumnView->GetListArray()->Reset(); iColumnView->RedrawL(); iNewControl=new(ELeave)CNewControl(this); iNewControl->ConstructL(); iNewControl->ActivateL(); AddToStackL(iNewControl); <!-- SIPO <DP n="46"> --> <dp n="d46"/> PhoneStat.SetSigral(25); PhoneStat.SetBattery(75); PhoneStat.SetMessages(0); /* if((Notifier-=StartThread(&PhoneStat,&NoteThread))=NULL) CEikonEnv∷Beep();*/ //install a periodic timer giving it a pointer to our AppUi as it′s parameter TCallBack cb(PollPhone,this); SmsTimer=CPeriodic∷NewL(-10); SmsTimer->Start(POLL_PHONE_RATE,POLL_PHONE_RATE,cb); // StartThread(this,&SMSThread); } TInt PollPhone(TAny*APtr) { // UserHal∷ModifyLedMask(KLedMaskGreedl,KLedMaskRedl); #if(KEEP_ON==1) UserHal∷ResetAutoSwitchOffTimer(); #erdif CFloatAppUi*ParentAppUi=(CFloatAppUi*)APtr; //run the sms state machine CNewWindow*Win=ParentAppUi->GetControl()->GetWindow(); #ifdef WANT_SERIAL ParentAppUi->SMSUtils->DoSMSState(Win); #else // Wait(2000000); #endif CSMSUtil*SMS=ParentAppUi->SMSUtils->GetSMSUtil(); if(ParentAppUi->SMSUtils->SMS_State=SERIAL_CLEAR) { ParentAppUi->SMSUtils->SMS_State=DO_NOTHING;//reset state machine if(SMS->gottoken) { <!-- SIPO <DP n="47"> --> <dp n="d47"/> SMS->gottoken=FALSE; DoConnect(ParentAppUi); } } return(TRUE); } CFloatAppUi∷~CFloatAppUi() { // delete iFloatControl; delete iNewControl; delete SmsTimer; delete iColumnView; #ifndef_WINS_ SMSUtils->ClosePort(); #endif delete SMSUtils; SMSThread.Terminate(0); // Notifier->Close(); } void CFloatAppUi∷HandleCommandL(TInt aCommand) { switch(aCommand) { case EEikCmdExit: FloatExit(); } } void CFloatAppUi∷SetWindowSizeL(TSize aControlSize) { iNewControl->SetExtentL(iNewControl->PositionRelativeToScreep(), aControlSize); } TSize CFloatAppUi∷WindowSize() { return iNewControl->Size(); } void CFlotAppUi∷FloatExit() <!-- SIPO <DP n="48"> --> <dp n="d48"/> { iCoeEnv->Flush(200000); CBaActiveScheduler∷Exit(); } ///////////////////////////////////////////////////////////////////////////////////// // // 类 CFloatDocument // CEikAppUi*CFloatDocument∷CreateAppUiL() { return(new(ELeave)CFloatAppUi); } //////////////////////////////////////////////////////////////////////////////////// // //class CFloatApplication // TUid CFloatApplication∷AppDllUid()const { return(KUidFloatApp); } CApaDocument*CFloatApplication∷CreateDocumentL() { return(new(ELeave)CFloatDocument(*this)); } ///////////////////////////////////////////////////////////////////////////////////// // //EXPORTed 函数 // EXPORT_C CApaApplication*NewApplication() { return(new CFloatApplication); } GLDEF_C TInt E32D11(TD11Reason) { return(KErrNone); } ///////////////////////////////////////////////////////////////////////////////////// // // 类 CNewWindow <!-- SIPO <DP n="49"> --> <dp n="d49"/> // //显示浮动区的窗口。 //包括用于获得指针事件的所有代码, //更新浮动区指示符抓取并显示位图。 // CNewWindow∷CNewWindow() // //构造器 // { _DECLARE_NAME(_S(″CNewWindow″)); // SetNonFocusing(); } CNewWindow∷~CNewWindow() // //解构器 // { delete iBitmap; } void CNewWindow∷ConstructL() // // 装入位图以显示浮动区 // { iText=_L(″Notifier State″); TBufC<40>BitmapFile(_L(″\\evo\\allbms.mbm″));//!!EIKON service to do this in a soft-coded manner is forthcoming //set up name for bitmap sharing TBool shareIfLoaded(ETrue); TParse mbfn; TBufC<2>c_drive(_L(″C:″)); mbfn.Set(BitmapFile,&c_drive,NULL); iBitmap=new(ELeave)CFbsBitmap(); iBitmap->Load(mbfn.FullName(),EMbmBmapsBat,shareIfLoaded); } void CNewWindow∷SetActive(TBool aActive) // //启动指针抓取标记 // { iActive=aActive; } <!-- SIPO <DP n="50"> --> <dp n="d50"/> inline TBool CNew Window∷Active()const // // 返回实际的标记 // { return iActive; } TSize CNewWindow∷MinimumSize() // // 组件的最小尺寸 // { //最小尺寸是1个象素的窗口轮廓。 return TSize(1,1); } void CNewWindow∷SizeChangedL() { } /*void CNewWindow∷UpdateNow(TPtrC NewText) { iText=NewText; DrawNow(); // ControlEnv()->WsSession().Flush(); }*/ void CNewWindow∷HandlePointerEventL(const TPointerEvent&aPointerEvent) { // if(!Active()) // return; if(aPointerEvent.iType==TPointerEvent∷EButtonlUp) { } else if(aPointerEvent.iType=TPointerEvent∷EButtonlDown) { SetFocus(ETrue); } else if(aPointerEvent.iType==TPointerEvent∷EDrag) { // SetFloatCentre(aPointerEvent.iParentPosition); } } void CNewWindow∷Draw(const TRect&/*aRect*/)const // // 画出窗口 // { CWindowGc&gc=SystemGc(); <!-- SIPO <DP n="51"> --> <dp n="d51"/> // 画边框 TRect rect=Rect(); // rect.Shrink(ENewMargin,ENewMargin); gc.DrawRect(rect); TInt LeftX=rect.iTl.iX+ENewMargin; const CFont*Font=iEikonEnv->LegendFont(); gc.SetPenColor(KRgbBlack); //set pen colour gc.SetBrushStyle(CGraphicsContext∷ENullBrush); gc.UseFont(Font); //前部 //文本开始。 TRect BoxRect(TPoint(LeftX+2,(rect.iBr.iY-Font->HeightInPixels()- 8)),TSize(ETextBoxWidth,Font->HeightInPixels()+6)); gc.SetBrushColor(KRgbWhite); //set pen colour gc.SetBrushStyle(CGraphicsContext∷ESolidBrush); gc.DrawRect(BoxRect); gc.DrawText(iText,TPoint(LeftX+5,rect.iBr.iY-Font->DescentInPixels()-5)); // then draw it TPoint pos(LeftX+2,rect.iTl.iY+2); // gc.BitBlt(pos,iBitmap); } ///////////////////////////////////////////////////////////////////////////////////// // // 类 CNewControl // //用于 CNewWindow的控制类。 // CNewControl∷CNewControl(CFloatAppUi*anAppUi) :iParentAppUi(anAppUi) // //构造器 // { _DECLARE_NAME(_S(″CNewControl″)); } CNewControl∷~CNewControl() <!-- SIPO <DP n="52"> --> <dp n="d52"/> // // 解构器 // { delete iMover; delete iClose; delete iNewWindow; delete iTestButton; } CEikCommandButton*CNewControl∷NewButton(const TDesC8&text) { CEikCommandButton*iButton=new(ELeave)CEikCommandButton; iButton->SetContainerWindowL(*this); iButton->SetObserver((class MCoeControlObserver*)this); iButton->SetTextL(text); iButton->Label()->iAlignment=EHCenterVTop; return(iButton); } void CNewControl∷ConstructL() // //用于CNewControl的实际构造器 // { // 父窗口 // iCoeEnv=aCoeEnv; CreateWindowL(); ErableDragEvents(); Window().SetPointerGrab(ETrue); Windlow().ClaimPointerGrab(); Window(),EnableBackup(); iEikonEnv->AddWindowShadow(this); //移动条组件 iMover=new(ELeave)CEikMover; iMover->SetContainerWindowL(*this); { TBuf<32>title; iEikonEnv->ReadResource(title,R_NEW_TITLE); iMover->SetTextL(title); } iMover->SetActive(ETrue); iTestButton=NewButton(_L(″Test″)); TSize dialbuttonsize=iTestButton->MinimumSize(); <!-- SIPO <DP n="53"> --> <dp n="d53"/> iNewRect.SetRect( ENewMargin, ENewMargin+ENewTitleHeight, ENewMargin+ENewWidth, ENewMargin+ENewTitleHeight+ENewHeight); #ifdef WANT WINDOW //区域新组件 iNewWindow=new(ELeave)CNewWindow(); iNewWindow->ConstructL(); iNewWindow->SetContainerWindowL(*this); iNewWindow->SetRectL(iNewRect); iNewWindow->SetActive(ETrue); #endif //nuke组件 iClose=new(ELeave)CFloatCloseAppUi(iParentAppUi); iClose->SetContainerWindowL(*this); iClise->SetRectL(TRect( ENewWindowWidth-ENewTitleHeight,0, ENewWindowWidth,ENewTitleHeight)); TSize containersize(ENewWindowWidth,ENewWindowHeight); containersize.iHeight+=(iTestButton- >MinimumSize().iHeight+TOTAL_MARGIN); SetExtentL(TPoint(0,0),containersize); TPoint buttonposition; buttonposition.iX=(containersize.iWidth-(dialbuttonsize.iWidth+ENewMargin)-2); buttonposition.iY=(containersize.iHeight-(dialbuttonsize.iHeight))/2; //(containersize.iHeight-(dialbuttonsize.iHeight+BUTTON_TOP_MARGIN)); iTestButton->SetExtentL(buttonposition,dialbuttonsize);//设置按钮的范围。 SetPosition(TPoint(420,5)); } void CNewControl∷SizeChangedL() // //就变化了的窗口尺寸重置移动器的尺寸 // { TRect rect=Rect(); rect.Shrink(1,1); rect.iBr.iY=rect.iTl.iY+ENewTitleHeight; rect.iBr.iX-=ENewTitleHeight; iMover->SetRectL(rect); rect.iTl.iX=rect.iBr.iX; <!-- SIPO <DP n="54"> --> <dp n="d54"/> rect.iBr.iX+=ENewTitleHeight; iClose->SetRectL(rect); iNewRect.SetRect(TPoint(ENewMargin,ENewMargin+ENewTitleHeight), TSize(iSize.iWidth-ENewMargin*2, iSize.iHeight-ENewMargin*2- ENewTitleHeight)); #ifdef WANT_WINDOW iNewWindow->SetRectL(iNewRect); #endif // iNewResizer- >SetRectL(TRect(iNewRect.iBr,iNewRect.iBr+TPoint(ENewMargin,ENewMargin))); DrawNow(); } void CNewControl∷Draw(const TRect&/*aRect*/)const // // 画 CNewControl 窗口 // { TRect rect=Rect(); CWindowGc&gc=SystemGc(); gc.Clear(); gc.DrawRect(rect); } TInt CNewControl∷CountComponentControls()const // // 窗口中组件的数量 // { #ifdef WANT_WINDOW return(4); #else return(3); #endif } CCoeControl* CNewControl∷ComponentControl(TInt aIndex)const // //返回访问移动器和新区域 // { switch(aIndex) { case0: return iMover; case 1: return iTestButton; #ifdef WANT_WINDOW <!-- SIPO <DP n="55"> --> <dp n="d55"/> case 2: return iNewWindow; #endif default: return iClose; } } TSize CNewControl∷MinimumSize() { return TSize(ENewMargin*2, ENewMargin*2+ENewTitleHeight+31); } void CNewControl∷HandleControlEventL(CCoeControl*aControl,TCoeEvent aEventType) { switch(aEventType) { //控件要失于焦点 case EEventPrepareFocusTransition: { TInt aind=Index(aControl); } break; //控件要获得焦点 case EEventRequestFocus: { } break; case EEventStateChanged: { TInt ind=Index(aControl); if(ind==1) //挂起按钮 { DoConnect(iParentAppUi); } }break; default: break; } } TKeyResponse CNewControl∷OfferkeyEventL(const TKeyEvent& /*aKeyEvent*/,TEventCode aType) // //响应按键事件 // { if(aType!=EEventKey) <!-- SIPO <DP n="56"> --> <dp n="d56"/> return EKeyWasConsumed; return EKeyWasConsumed; } void DoConnect(CFloatAppUi*ParentAppUi) { TBuf<80>DebugText; TBufC<200>ReadBuffer; Tlnt ret; CNewWindow*Win=ParentAppUi->GetControl()->GetWindow(); unsigned char CipherText[256]; unsigned char TokenBuffer[32]; unsigned char key[25],iv[9]; ParentAppUi->AddLine(″Got Push Token″); ESMSUtil*SMSUtils=ParentAppUi->SMSUtils; CSMSUtil*SMS=ParentAppUi->SMSUtils->GetSMSUtil(); delete ParentAppUi->SmsTimer; //使计时器停止 ParentAppUi->SmsTimer=NULL; #ifndef_WINS_ SMSUtils->ClosePort(); //释放IR端口 #endif int donebytes; //10,testuser,password,0011223344556677,2BvGbF4s9HBSt9f/g24EVw,99/01/10 17:43 #ifdef EMBED_TOKEN int tsize=from64(″2BvGbF4s9HBSt9f/g24EVw″,22,&SMS->token[0],&donebytes); SMS->token[tsize]=0; // tsize=from64(&src[28],8,&SMS->token_index[0],&donebytes); memcpy(&SMS->token_index[0],″\x00\x00\x0a\x00\x00\x00\x00″,7); #endif char*EncStr=GenerateString(parentAppUi,SMS->token,SMS->token_index,key,iv); if(EncStr==NULL) <!-- SIPO <DP n="57"> --> <dp n="d57"/> { DebugText.Format(_L(″No String″)); ParentAppUi->AddLine(DebugText); } else { DebugText.Format(_L(″%s″),EncStr); ParentAppUi->AddLine(DebugText); ParentAppUi->AddLine(″About to do connect″); RSocketServ SockServer; if(SockServer.Connect()==KErrNone) { ParentAppUi->AddLine(″Connected to socket server″); CWSocket*Socket=new CWSocket(&SockServer); if(Socket!=NULL) { ∥ ret=Socket->Connect(25,_L(″eltham.dsres.com″)); ret=Socket->Connect(25,_L(″jmfport.dsres.com″)); if(ret>=0) { ParentAppUi->AddLine(″Connected!″); PatClient Pat(parentAppUi,SMS->token,key,iv); Pat.process_smtp(Socket,EncStr); } else { DebugText.Format(_L(″Connected Failed%d″),ret); ParentAppUi->AddLine(DebugText); } Socket->Close(); delete Socket; Socket=NULL; } else { DebugText.Format(_L(″Failed to create socket″)); ParentAppUi->AddLine(DebugText); } ParentAppUi->AddLine(″Closing socket server″); <!-- SIPO <DP n="58"> --> <dp n="d58"/> SockServer.Close(); ParentAppUi->AddLine(″socket server closed″); } else { DebugText.Format(_L(″Couldn′t connect to socket server″)); ParentAppUi->AddLine(DebugText); } } Wait(5000000); int r,count=0; #ifndef_WINS_ do { r=SMSUtils->OpenPort(); //获取IR端口 if(r<0) { ShowDebug(_L(″Waiting for IR Port to be released″),10000000); count++; } }while((r<0)&&(count<5)); #endif //安装周期性计时器以便作为参数给以指向AppUi的指针 TCallBack cb(PollPhone,ParentAppUi); ParentAppUi->SmsTimer=CPeriodic∷NewL(-10); ParentAppUi->SmsTimer->Start(POLL_PHONE_RATE,POLL_PHONE_RATE,cb); ParentAppUi->AddLine(″IR Port opened″); } //仅将一个参数传给新线程,从而创建用其传递 //SMSStats类的结构以及用其发出已开始的信号。 //还可用于传回指向所创建的CNotifier类的指针。 struct StatSemaphore{ CFloatAppUi*AppUi; RSemaphore*semaphore; }; TInt ThreadFunction(TAny*anArg) { <!-- SIPO <DP n="59"> --> <dp n="d59"/> StatSemaphore&TempStat=*(StatSemaphore*)anArg; CFloatAppUi*ParentAppUi=TempStat.AppUi; TempStat.semaphore->Signal(); TInt Leave=FALSE; do { PollPhone(ParentAppUi); Wait(POLL_PHONE_RATE); }while(Leave==FALSE); return(KErrNone}; } //创建通知器服务器线程。用所传送的线程参数 //保持最新创建的线程的指针, //因此能在主过程关闭时终止该线程。 void StartThread(CFloatAppUi*ParentAppUi,RThread*thread) { StatSemaphore TempStat; RSemaphore semaphore; semaphore.CreateLocal(0);//创建信号,因此知道线程何时开始 has started TempStat.semaphore=&semaphore; TempStat.AppUi=ParentAppUi; TInt res=thread->Create(_L(″SmsThread″),//create new server thread ThreadFunction,//线程的主函数 KDefaultStackSize, KDefaultHeapSize, KDefaultHeapSize, &TempStat//作为TAny*参数传给线程函数 ); if(res==KErrNone)//thread created ok-now start it going { thread->SetPriority(EPriorityNormal); thread->Resume();//开始 semaphore.Wait();//等待直被初始化 } <!-- SIPO <DP n="60"> --> <dp n="d60"/> else//未创建线程ok { thread->Close();//不再对其感兴趣 } semaphore.Close(); }
/*附录 9:crypt.h*/ #ifndef_CRYPT_H #define_CRYPT_H #include″endec64.h″ #include″des.h″ struct ctx_3des { des_key_schedule ks1,ks2,ks3; unsigned char iv[8]; }; class CFloatAppUi; char*GenerateString(CFloatAppUi*ParentAppUi,unsigned char*Random Token,unsigned char*TokenIndex, unsigned char*key,unsigned char*iv); void Encrypt(ctx_3des*ctx,unsigned char*dest,unsigned char*src,int len); void Decrypt(ctx_3des*ctx,unsigned char*dest,unsigned char*src,int len); void GenerateKey(unsigned char*key,int keylen,unsigned char Random Token[16],CFloatAppUi*ParentAppUi); void InitKey(ctx_3des*ctx,unsigned char*key,unsigned char*iv,int*des_check_key); long AsciiToHex(ursigned char*dst,const unsigned char*src,long len); #endif
/*附录 10:crypt.cpp*/ #include<stcio.h> #include<stdlib.h> #include<string.h> #include<eikcmbut.h> #include″pushnot.h″ #include″crypt.h″ #include″getput.h″ #include″hash.h″ const char HexTab[16]={′0′,′1′,′2′,′3′,′4′,′5′,′6′,7′,′8′,′9′,′A′,′B′,′C′,′D′,′E′,′F′}; long AsciiToHex(unsigned char*dst,const unsigned char*src,long len) { long i; for(=0;i<len;i++) { *(dst++)=HexTab[(*src)>>4]; *(dst++)=HexTab[(*src)&0x0f]; src++; } *(dst++)=0; return(i*2+1); } void CopyMemory(void*Dest,void*Source,long len) { memcpy(Dest,Source,len); } void GenerateKey(unsigned char*key,int keylen,unsigned char Random Token[16],CFloatAppUi*ParentAppUi) { unsigned char EvoKey[8]; unsigned char HexBuf[256]; // unsigned char Random Token[16]; // 示例的EVO安装密钥是0011223344556677 memcpy(EvoKey,″\x00\x11\x22\x33\x44\x55\x66\x77″,8); <!-- SIPO <DP n="63"> --> <dp n="d63"/> Hash md5(SSH_HASH_MD5); md5.Add(EvoKey,sizeof(EvoKey)); md5.Add(Random Token,16); CopyMemory(key,md5.Digest(),(keylen>=16)?16:keylen); TBuf<128>WBuf; AsciiToHex(&HexBuf[0],key,16); WBuf.Format(_L(″Md5 Digest=%s″),&HexBuf[0]); ParentAppUi->AddLine(WBuf); for(int len=16;(keylen-=16)>0;len+=16){ md5.Init(SSH_HASH_MD5); md5.Add(EvoKey,sizeof(EvoKey)); md5.Add(key,len); CopyMemory(key+len,md5.Digest(),(keylen>=16)?16:keylen); } } int des_ede_encrypt(unsigned char*input,unsigned char*output, des_key_schedule ks1, des_key_schedule ks2,des_key_schedule ks3,int encrypt) { unsigned long 11[2]; 11[0]=GetLong_Little(input); 11[1]=GetLong_Little(input+4); des_encrypt(11,11,ks1,encrypt); des_encrypt(11,11,ks2,!encrypt); des_encrypt(11,11,ks3,encrypt); PutLong_Little(output,11[0]); PutLong_Little(output+4,11[1]); return(0); } void des3_cbc(unsigned char*dest, const unsigned char*src,int len, des_key_schedule ks1,des_key schedule ks2, des_key_schedule ks3,ursigned char*iv, int for_encryption) { int n; if(for_encryption){ while(len>0){ unsigned char input[8]; for(n=0;n<8;++n) input[n]=src[n]^iv[n]; des_ede_encrypt(input,iv,ks1,ks2,ks3,1); <!-- SIPO <DP n="64"> --> <dp n="d64"/> memcpy(dest,iv,8); src+=8; dest+=8; len-=8; } } else{ while(len>0){ unsigned char output[8]; des_ede_encrypt((unsigned char*)src,output,ks1,ks2,ks3,0); for(n=0;n<8;++n) dest[n]=output[n]^iv[n]; memcpy(iv,src,8); src+=8; dest+=8; len-=8; } } } void InitKey(ctx_3des*ctx,unsigned char*key,unsigned char*iv,int*des_check_key) { des_set_key((des_cblock*)key,ctx->ks1,des_check_key); des_set_key((des_cblock*)(key+8),ctx->ks2,des_check_key); des_set_key((des_cblock*)(key+16),ctx->ks3,des_check_key); memcpy(ctx->iv,iv,8); } void Encrypt(ctx_3des*ctx,unsigned char*dest,unsigned char*src,int len) { des3_cbc(dest,src,len,ctx->ks1,ctx->ks2,ctx->ks3,ctx->iv,1); } void Decrypt(ctx_3des*ctx,unsigned char*dest,unsigned char*src,int len) { des3_cbc(dest,src,len,ctx->ks3,ctx->ks2,ctx->ks1,ctx->iv,0); } static int CryptTest() { ctx_3des ctx_enc,ctx_dec; unsigned char plaintext[256],ciphertext[256],control[256]; int des_check_key=0; unsigned char key[24],iv[8]; memcpy(key,″\x11\x11\x22\x22\x33\x33\x44\x44\x55\x55\x66\x66\x77\x77\x88\x88 \x99\x99\x00\x00\xaa\xaa\xbb\xbb″,24); <!-- SIPO <DP n="65"> --> <dp n="d65"/> memcpy(iv,″\x11\x11\x22\x22\x33\x33\x44\x44″,8); memcpy(plaintext,″Hi I am a cool epoc program″,28); //random_state.GetData(plaintext,sizeof(plaintext)); InitKey(&ctx_enc,key,iv,&des_check_key); Encrypt(&ctx_enc,ciphertext,plaintext,sizeof(plaintext)); InitKey(&ctx_dec,key,iv,&des_check_key); Decrypt(&ctx_dec,control,ciphertext,sizeof(plaintext)); return memcmp(control,plaintext,sizeof(plaintext)); } const char MessText2[6]=″@ewi″; char*GenerateString(CFloatAppUi*ParentAppUi,unsigned char*RandomToken,unsigned char*TokenIndex, unsigned char*key,unsigned char*iv) { ctx_3des ctx_enc; unsigned char CipherText[256]; unsigned char TokenBuffer[32]; unsigned char HexBuf[256]; // unsigned char key[25],iv[9]; int des_check_key=0; key[24]=iv[8]=0; //用于打印 Hash md5(SSH_HASH_MD5); md5.Add(RandomToken,16); CopyMemory(TokenBuffer,md5.Digest(),16); TBuf<128>WBuf; AsciiToHex(&HexBuf[0],RandomToken,16); WBuf.Format(_L(″Token=%s″),&HexBuf[0]); ParentAppUi->AddLine(WBuf); AsciiToHex(&HexBuf[0],TokenBuffer,16); WBuf.Format(_L(″Hashed Token=%s″),&HexBuf[0]); ParentAppUi->AddLine(WBuf); GenerateKey(key,24,′K′,Random Token,ParentAppUi); AsciiToHex(&HexBuf[0],key,24); WBuf.Format(_L(″key=%s″),&HexBuf[0]); ParentAppUi->AddLine(WBuf); GenerateKey(iv,8,′I′,RandomToken,ParentAppUi); <!-- SIPO <DP n="66"> --> <dp n="d66"/> AsciiToHex(&HexBuf[0],iv,8); WBuf.Format(_L(″iv=%s″),&HexBuf[0]); ParentAppUi->AddLine(WBuf); InitKey(&ctx_enc,key,iv,&des_check_key); Encrypt(&ctx_enc,CipherText,TokenBuffer,16); AsciiToHex(&HexBuf[0],CipherText,16); WBuf.Format(_L(″Encrypted=%s″),&HexBuf[0]); ParentAppUi->AddLine(WBuf); const char*CipherText64=to64(CipherText,16); const char*TokenIndex64=to64(TokenIndex,6); AsciiToHex(&HexBuf[0],(const unsigned char*)CipherText64,22); WBuf.Format(_L(″Encrypted64=%s″),&HexBuf[0]); ParentAppUi->AddLine(WBuf); AsciiToHex(&HexBuf[0],(const unsigned char*)TokenIndex64,8); WBuf.Format(_L(″TokenIndex64=%s″),&HexBuf[0]); ParentAppUi->AddLine(WBuf); int TotalLen=strlen(TokenIndex64)+1+strlen(CipherText64)+strlen(MessText2); char*retstr=(char*)malloc(TotalLen); if(retstr!=NULL) { sprintf(retstr,″%s.%s%s″,TokenIndex64,CipherText64,MessText2); } free((void*)TokenIndex64); free((void*)CipherText64); return(retstr); }
/*附录 11:client.h*/ #ifndef_CLIENT_H #define_CLIENT_H #include″socket.h″ #include<stdio.h> #include<string.h> #define SMTP_TIMEOUT 100000000 #define BIG_BUF 4096 #define OK 250 #define TMP_IN 0 #define TMP_OUT 1 class CFloatAppUi; struct lumpIO { FILE*f; unsigned char key[24],iv[8]; ctx_3des ctx_dec; }; class PatClient { public: PatClient(CFloatAppUi*ParentAppUi,unsigned char*RT,unsigned char*k,unsigned char*i); void GenFCount(RFs&FS); TInt send file(RFs&FS,char*filename,CWSocket*Sock); void to_upper(char*str); void process_queue_for_user(RFs&FS,const char*user,CWSocket*Sock); void process_smtp(CWSocket*Sock,char*EncStr); int read_smtp_reply(CWSocket*Sock,TPtr buf); int timed_read_line(CWSocket*Sock,TPtr buf,int TimeOut); int mail_rcpt_addr(TPtr buf,TPtr addr); void process_state(int state,CWSocket*Sock,TPtr addr); int Logon(CWSocket*Sock,char*EncStr); int SendAndWait(CWSocket*Sock,TPtrC SendStr,TPtr ReadBuf); int SendAndGet(CWSocket*Sock,TPtrC SendStr,TPtr ReadBuf); FILE*create_tmp(int where,char*tmp,const char*user); void Rename(RFs&FS,char*from,char*to); <!-- SIPO <DP n="68"> --> <dp n="d68"/> struct lumpIO*lumpIO_init(unsigned char key[24],unsigned char iv[8],FILE*f ); unsigned char*lumpIO_fgets(unsigned char*buf,int buflen,struct lumpIO*lio); int lumpIO_fputs(char*string,struct lumpIO*lio); TBuf<40>client_vetsion; // TBuf<40>user; TInt FCount; CFloatAppUi*ParentAppUi; struct lumpIO lumpIO; int des_check_key; unsigned char*RandomToken; unsigned char*key,*iv; }; enum{ST_INIT,ST_MAIL_CLIENT_VERS,ST_RCPT_SERVER_VERS, ST_RCPT_TOKEN,ST_MAIL_OUT,ST_RCPT_OUT,ST_DATA_OUT, ST_MAIL_IN,ST_RCPT_IN,ST_DATA_IN}; #endif
/*附录 12:client.cpp*/ #include<e32cons.h> #include<s32file.h> #include<d32dbms.h> #inchude<eikcmbut.h> #include″crypt.h″ #include″socket.h″ #include″client.h″ #include″pushnot.h″ #define IN_NAME (″\\pat\\in\\″) #define OUT_NAME(″\\pat\\out\\″) #define CLIENT_VERSION(″01″) #define SERVER_VERSION(″01″) void ShowDebug(TDesC8&Text,TTimeIntervalMicroSeconds32 Delay) { User∷InfoPrint(Text); User∷After(Delay); } const char user[20]=″EpocClient@ewi″; const char server[20]=″PatServer@ewi; //构造器 PatClient∷PatClient(CFloatAppUi*AppUi,unsigned char*RT,unsigned char*k,unsigned char*i) { ParentAppUi=AppUi; des_check_key=0; RandomToken=RT; key=k;iv=i; } int PatClient∷read_smtp_reply(CWSocket*Sock,TPtr buf) { int ret; if(timed_read_line(Sock,buf,SMTP_TIMEOUT)<0) return-1; sscanf((const char*)buf.Ptr(),″%d″,&ret); // TBuf<128>WBuf; <!-- SIPO <DP n="70"> --> <dp n="d70"/> // WBuf.Format(_L(″read%S,returning%d″),buf,ret); // ParentAppUi->AddLine(WBuf); return(ret); } int PatClient∷timed_read_line(CWSocket*Sock,TPtr buf,int TimeOut) { TBuf<1>aChar; TBuf<40>WBuf; char c=0,c2=0; int ret=1; int Count=0; buf.SetLength(0); while((Count<(buf.MaxLength()-1))&&((c!=′\n′)‖(c2!=′\r′))&&(ret==1)) { c2=c; ret=Sock->Read(aChar,TimeOut); if(ret==1) //we must read one byte { c=aChar[0]; buf.Append(aChar); Count++; } const TUint8*P=buf.Ptr(); } buf.Append(′\0′); if(ret==1) return(Count); else return(ret); } /* 检查缓冲区是否是‘某个cmd:地址’并用该地址填充地址 */ int PatClient∷mail_rcpt_addr(TPtr buf,TPtr addr) { TInt Colon=buf.March(_L(″*:<*>*″)); if(Colon<0)return(FALSE); Colon+=2;//move past< TInt End=buf.LocateReverse(′>′); <!-- SIPO <DP n="71"> --> <dp n="d71"/> addr.Copy(buf.Mid(Colon,End-Colon-1)); return(TRUE); } void PatClient∷process_state(int state,CWSocket*Sock,TPtr addr) { TBuf<128>TempBuff; switch(state) { case ST_MAIL_IN: { TempBuff.Format(_L(″250 OK\r\n″),addr); Sock->Write(TempBuff,SMTP_TIMEOUT); }break; case ST_RCPT_IN: { TempBuff.Format(_L(″250 OK\r\n″),addr); Sock->Write(TempBuff,SMTP_TIMEOUT); }break; default:break; } } int PatClient∷Logon(CWSocket*Sock,char*EncStr) { HBufC*buf=HBufC∷New(BIG_BUF); TBuf<200>WBuf; TInt ret,Exit=FALSE; ParentAppUi->AddLine(″Starting logon″); if(buf!=NULL) { do { ret=timed_read_line(Sock,buf->Des(),SMTP_TIMEOUT); if(ret<0) { ParentAppUi->AddLine(″Didn′t get ME PAT_SMTP″); delete buf; return(FALSE); <!-- SIPO <DP n="72"> --> <dp n="d72"/> } if(buf->Find(_L(″220 ME PAT_SMTP\r\n″))==0) { if(SendAndWait(Sock,_L(″HELO from Epoc Pat Client\r\n″),buf->Des())==FALSE) { break; delete buf; return(FALSE); } WBuf.Format(_L(″MAIL FROM:<%s>\r\n″),CLIENT_VERSION); if(SendAndWait(Sock,WBuf,buf->Des())==FALSE) { delete buf; return(FALSE); } // ShowDebug(_L(″Got reply to MAIL FROM″)); WBuf.Format(_L(″RCPT TO:<%s>\r\n″),SERVER_VERSION); if(SendAndWait(Sock,WBuf,buf->Des())==FALSE) { delete buf; return(FALSE); } // ShowDebug(_L(″Got reply to RCPT TO<server>″)); WBuf.Format(_L(″RCPT TO:<%s>\r\n″),EncStr); if(SendAndWait(Sock,WBuf,buf->Des())==FALSE) { delete buf; return(FALSE); } WBuf.Format(_L(″Got Reply to RCPT TO:<%s>″),EncStr); if(SendAndWait(Sock,_L(″TURN\r\n″),buf- >Des())==FALSE) { deiete buf; return(FALSE); } <!-- SIPO <DP n="73"> --> <dp n="d73"/> // ParentAppUi->AddLine(″Got reply to TURN″); Exit=TRUE; } }while(Exit==FALSE); delete buf; } else return(FALSE); return(TRUE); } //发送一个串并确定获得了OK int PatClient∷SendAndWait(CWSocket*Sock,TPtrC SendStr,TPtr ReadBuf) { TBuf<128>WBuf; // WBuf.Format(_L(″Sending%S″),SendStr,3000000); // ParentAppUi->AddLine(WBuf); if(Sock->Write(SendStr,SMTP_TIMEOUT)<0) { return(FALSE); } if(read_smtp_reply(Sock,ReadBuf)!=OK) { return(FALSE); } return(TRUE); } //发送一个串并获得应答 int PatClient∷SendAndGet(CWSocket*Sock,TPtrC SendStr,TPtr ReadBuf) { TInt ret; TBuf<128>WBuf; if((ret=Sock->Write(SendStr,SMTP_TIMEOUT))<0) { WBuf.Format(_L(″Write failed%d″),ret); ShowDebug(WBuf); return(-1); } return(read_smtp_reply(Sock,ReadBuf)); } <!-- SIPO <DP n="74"> --> <dp n="d74"/> void PatClient∷process_smtp(CWSocket*Sock,char*EncStr) { TInt Exit=FALSE; RFs FS=ParentAppUi->fileserver; if(!Logon(Sock,EncStr)) { ParentAppUi->AddLine(″Logon Failed″); return; } int state=ST_MAIL_IN; HBufC*buf=HBufC∷New(BIG_BUF); char*tmp1=new char[BIG_BUF]; char*tmp2=new char[BIG_BUF]; char*tmp_name=new char[BIG_BUF]; HBufC*rcpt_to=HBufC∷New(BIG_BUF); HBufC*mail_from=HBufC∷New(BIG_BUF); FILE*tmp_f; TBuf<200>DebugStr; //对接收到的电子邮件首先获得文件下标 GenFCount(FS); if(buf&&tmp1&&tmp2&&rcpt_to&&mail_from&&tmp_name) { do { if(timed_read_line(Sock,buf->Des(),SMTP_TIMEOUT)>0) { sscanf((const char*)buf->Ptr(),″%[^\r\n]%*[\t]%[^ \r\n]″,tmp1,tmp2); to_upper(tmp1); DebugStr.Format(_L(″Got command%s″),tmp1); ParentAppUi->AddLine(DebugStr); if(strcmp(tmp1,″MAIL″)==0) { if(mail_rcpt_addr(buf->Des(),mail_from->Des())) { if(state==ST_MAIL_IN) { // if ((tmp_f=create_tmp(TMP_IN,tmp_name,&user[0]))=NULL) <!-- SIPO <DP n="75"> --> <dp n="d75"/> if ((tmp_f=create_tmp(TMP_IN,tmp_name,(const char*)mail_from->Des().PtrZ()))==NULL) { Sock->Write(_L(″500 Can′t create temp file\r\n″),SMTP_TIMEOUT); } else { process_state(state,Sock,mail_from->Des()); } } else { Sock->Write(_L(″501 unexpected MAIL command\r\n″),SMTP_TIMEOUT); } } else { Sock->Write(_L(″500 Bad MAIL command\r\n″),SMTP_TIMEOUT); } } else if(strcmp(tmp1,″RCPT″)==0) { if(mail_rcpt_addr(buf->Des(),rcpt_to->Des())) { if(state==ST_MAIL_IN) { state=ST_RCPT_IN; process_state(state,Sock,rcpt_to- >Des()); } else { Sock->Write(_L(″501 unexpected RCPT command\r\n″),SMTP_TIMEOUT); } } else { Sock->Write(_L(″500 Bad RCPT command\r\n″),SMTP_TIMEOUT); } } else if(strcmp(tmp1,″DATA″)==0) { TInt bad_end=FALSE,end=FALSE; char*buf_save; char*s1; <!-- SIPO <DP n="76"> --> <dp n="d76"/> state=ST_MAIL_IN;//set state to get more mail after we finish here struct lumpIO*f=lumpIO_init(key,iv,tmp_f); Sock->Write(_L(″354 Enter message,ending with \″.\″on a line by itself\r\n″),SMTP_TIMEOUT); ParentAppUi->AddLine(″About to receive file″); do { if(timed_read_line(Sock,buf- >Des(),SMTP_TIMEOUT)<0) { bad_end=TRUE; end=TRUE; DebugStr.Format(_L(″Read timed out%s″),buf->Ptr()); ParentAppUi->AddLine(DebugStr); } else { buf_save=(char*)buf->Ptr(); // DebugStr.Format(_L(″Read %s:%d,%d,%d,%d″),buf_save,*buf_save,*(buf_save+1),*(buf_save+2),*(buf_save+3)); // ParentAppUi->AddLine(DebugStr); if(strcmp(buf_save,″.\r\n″)==0) { end=TRUE; } else { //if line is two′.′s together skip the first //because it′s used to represent a signal dot if (strcmp(buf_save,″..\r\n″)==0) buf_save++; char *s1=strrchr(buf_save,′\r′); if((s1!=NULL)&& (*(s1+1)==′\n′)) *s1=0; lumpIO_fputs(buf_save,f); } <!-- SIPO <DP n="77"> --> <dp n="d77"/> } }while(end==FALSE); fclose(tmp_f);//close the file //if file was recieved OK rename it from temp to normal if(!bad_end) { strcpy(tmp2,tmp_name); s1=strrchr(tmp2,′\\′);//point s1 at\before file name //and rename file from t*to j* s1[1]=′j′; Renane(FS,tmp_name,tmp2); Sock->Write(_L(″250 OK\r\n″),SMTP_TIMEOUT); } } else if(strcmp(tmp1,″TURN″)==0) { if(state==ST_MAIL_IN) { state=ST_MAIL_OUT; Sock->Write(_L(″250 OK turning(sending mail to server)\r\n″),SMTP_TIMEOUT); //now fall through to end of loop } else { Sock->Write(_L(″501 unexpected turn command\r\n″),SMTP_TIMEOUT); } } else if(strcmp(tmp1,″QUIT″)==0) { Sock->Write(_L(″221 closing\r\n″),SMTP_TIMEOUT); Exit=TRUE; } else { Sock->Write(_L(″500 command unrecognised\r\n″),SMTP_TIMEOUT); } if(state==ST_MAIL_OUT) { process_queue_for_user(FS,&user[0],Sock); <!-- SIPO <DP n="78"> --> <dp n="d78"/> state=ST_MAIL_IN; // if(SendAndWait(Sock,_L(″TURN\r\n″),buf- >Des())==FALSE) // { //收发邮件,因此停止 Sock->Write(_L(″QUIT \r\n″),SMTP_TIMEOUT); Exit=TRUE; // } } } else { Exit=TRUE; } }while(Exit==FALSE); } // Sock->Write(_L(″200′Byeeeee from Epoc client\r\n″),SMTP_TIMEOUT); delete buf;delete[]tmp1; delete[]tmp2;delete rcpt_to; delete mail_from;delete[]tmp_name; } FILE*PatClient∷create_tmp(int where,char*tmp,const char*user) { if(where==TMP_IN) { sprintf(tmp,″%st%s.p%d″,IN_NAME,user,FCount++); } else sprintf(tmp,″%st%s.pat″,OUT_NAME,user,FCount++); return(fopen(tmp,″w+″)); } void PatClient∷process_queue_for_user(RFs&FS,const char*user,CWSocket*Sock) { char FullName[128]; TBuf<128>DirName; TBuf<128>WBuf; FILE*f; CDir*dirList; TInt i,End=FALSE; TEntry TempEntry; // ShowDebug(_L(″Sending Mail″)); DirName.Format(_L(″%sj*″),OUT_NAME); //分类目录 <!-- SIPO <DP n="79"> --> <dp n="d79"/> int Err=FS.GetDir(DirName,KEntryAttMaskSupported,ESortByName,dirList); if(Err<0)return; //no such directory //获得有多少文件 TInt NumItems=dirList->Count(); //逐一发送文件 for(i=0;((i<NumItems)&&(End==FALSE));i++) { TempEntry=(*dirList)[i]; sprintf(FullName,″%s%s″,OUT_NAME,TempEntry.iName.Des().PtrZ()); // WBuf.Format(_L(″sending%s″),FullName); // ShowDebug(WBuf,3000000); if(!send_file(FS,FullName,Sock)) { ShowDebug(_L(″Send File failed″)); //we failed to send the file End=TRUE; } // else // ShowDebug(_L(″Oh My God!It worked!!″)); } delete dirList; if(End) ShowDebug(_L(″Mail send Failed″)); else ShowDebug(_L(″All files sent OK″)); } TInt PatClient∷send_file(RFs& FS,char*filename,CWSocket*Sock) { FILE*qf; int ret; TBool eof_ok=FALSE; TBuf<128>TempBuff; //see if there is a file first!and return with error if not if((qf=fopen(filename,″r″))==NULL) { return(FALSE); } <!-- SIPO <DP n="80"> --> <dp n="d80"/> HBufC*tmp=HBufC∷New(BIG_BUF); TempBuff.Format(_L(″Sending file%s″),filename); ShowDebug(TempBuff); if(tmp!=NULL) { TempBuff.Format(_L(″MAIL FROM:<%s>\r\n″),&user[0]); if(SendAndWait(Sock,TempBuff,tmp->Des())==FALSE) { delete tmp; return(FALSE); } TempBuff.Format(_L(″RCPT TO:<%s>\r\n″),&server[0]); if(SendAndWait(Sock,TempBuff,tmp->Des())==FALSE) { delete tmp; return(FALSE); } ret=SendAndGet(Sock,_L(″DATA\r\n″),tmp->Des()); if(!((300<=ret)&&(ret<=399))) { TempBuff.Format(_L(″bad response to DATA%d\r\n″),ret); ParentAppUi->AddLine(TempBuff); delete tmp; return(FALSE); } char*tmp2=new char[BIG_BUF]; struct lumpIO*f=lumpIO_init(key,iv,qf); TInt Length=0; // while(fgets(tmp2,BIG_BUF,qf)!=NULL) while(lumpIO_fgets((unsigned char*)tmp2,BIG_BUF,f)!=NULL) { //由于对行进行了base64操作故在加密之后, //不需检查′.\r\n′.因为,该字串不会出现 //(不在base64字符集内) #ifdef UNENCRYPTED //如果在一行中因自己的缘故是a′.′则加a′.′, //否则接收器认为是末尾 <!-- SIPO <DP n="81"> --> <dp n="d81"/> if(strcmp(tmp2,″.\r\n″)==0) strcpy(tmp2,″..\r\n″); tmp->Des().Format(_L(″%s\r\n″),tmp2); #else tmp->Des().Format(_L(″%s″),tmp2); #endif // ShowDebug(_L(″Just Waiting″),1000000); Length+=tmp->Des().Length(); // ParentAppUi->AddLine(tmp->Des()); Sock->Write(tmp->Des(),SMTP_TIMEOUT); } TempBuff.Format(_L(″Sent%d bytes″),Length); ParentAppUi->AddLine(TempBuff); fclose(qf); if((ret=SendAndGet(Sock,_L(″.\r\n″),tmp->Des()))!=OK) { TempBuff.Format(_L(″bad reply to email%d\r\n″),ret); ParentAppUi->AddLine(TempBuff); delete[]tmp2; delete tmp; return(FALSE); } //need to do rename here stropy(tmp2,filename); char*s1=strrchr(tmp2,′\\′);//point s1 at\before file name //and rename file from j*to d* s1[1]=′d′; Rename(FS,filename,tmp2); delete[]tmp2; delete tmp; return(TRUE); } return(FALSE); } void PatClient∷to_upper(char*str) { char c; while((c=*str)) { if((c>=′a′)&&(c<=′z′)) { *str-=(′a′-′A′); } <!-- SIPO <DP n="82"> --> <dp n="d82"/> str++; } } void PatClient∷Rename(RFs&FS,char*from,char*to) { TPtrC From=TPtrC((TUint8*)from); TPtrC To=TPtrC((TUint8*)to); FS.Rename(From,To); } void PatClient∷GenFCount(RFs&FS) { char FullName[128],*s1; TBuf<128>DirName; TBuf<128>WBuf; FILE*f; CDir*dirList; TInt i,c; TEntry TempEntry; DirName.Format(_L(″%sj*.p”),IN_NAME); //找出所有的′j*.p*′文件 int Err=FS.GetDir(DirName,KEntryAttMaskSupported,ESortByName,dirList); FCount=0; if(Err<0)return; TInt NumItems=dirList->Count(); //检查以找出哪个具有.p范围 //之后的最高值 for(i=0;i<NumItems;i++) { TempEntry=(*dirList)[i]; sprintf(FullName,″%s″,TempEntry.iName.Des().PtrZ()); s1=strrchr(FullName,′.′);//point s1 at′file extension′before file name //获得.p后的值 sscanf((const char*)(s1+2),″%d″,&c); c++; //需要下一个可用的, 故使其递增 //如果大于当前最大值,则使用它。 if(c>FCount)FCount=c; } delete dirList; } <!-- SIPO <DP n="83"> --> <dp n="d83"/> struct lumpIO* PatClient∷lumpIO_init(unsigned char key[24],unsigned char iv[8],FILE*f) { memcpy(lumpIO.key,key,24); memcpy(lumpIO.iv,iv,8); /*here we generate the DES key*/ GenerateKey(lumpIO.key,24,RandomToken,ParentAppUi); /*here we generate the DES initialisation vector*/ GenerateKey(lumpIO.iv,8,RandomToken,ParentAppUi); InitKey(&lumpIO.ctx_dec,lumpIO.key,lumpIO.iv,&des_check_key); lumpIO.f=f; return&lumpIO; } /* 从文件中读出数据并对数据作加密和base64编码。 * 加密例程仅能处理是8 AND 6的倍数的数据, * 因此,数据块中的fread()对数据加密和编码。 * 但是,由于可能部分地填充最后的数据块, * 故必须传送数据的长度,最好传送所有块的长度, * 所以,发送的数据是长度未用的72字节数据=74字节。 */ #define LUMP_LENGTH 74 #define LUMP_DATA_LEN(LUMP_LENGTH-2) struct lump { char length; char unused; unsigned char data[LUMP_DATA_LEN+16]; }; unsigned char*PatClient∷lumpIO_fgets(unsigned char*buf,int buflen,struct lumpIO*lio) { struct lump 1; unsigned char tmp_in[LUMP_DATA_LEN+16]; TBuf<256>WBuf; l.data[LUMP_DATA_LEN]=tmp_in[LUMP_DATA_LEN]=′M′; if((l.data[LUMP_DATA_LEN]!=′M′)‖(tmp_in[LUMP_DATA_LEN]!=′M′)) { ShowDebug(_L(″Corruption at start″)); } <!-- SIPO <DP n="84"> --> <dp n="d84"/> /* 本例程不能处理对小缓冲区的fgets调用 */ if(buflen<LUMP_DATA LEN) return NULL; FILE*f=lio->f; if(feof(f)‖ferror(f)) return NULL; int in=fread(&tmp_in[0],sizeof(char),LUMP_DATA_LEN,f); if(in<0) return NULL; if((l.data[LUMP_DATA_LEN]!=′M′)‖(tmp_in[LUMP_DATA_LEN]!=′M′)) { ShowDebug(_L(″Corruption after read″)); } // WBuf.Format(_L(″Read%d bytes″),in); // ShowDebug(WBuf); l.length=(char)in; l.unused=0; Encrypt(&lio->ctx_dec,&l.data[0],&tmp_in[0],LUMP_DATA_LEN); if((l.data[LUMP_DATA_LEN]!=′M′)‖(tmp_in[LUMP_DATA_LEN]!=′M′)) { ShowDebug(_L(″Corruption after encrypt″)); } to64((unsigned char*)&l,LUMP_LENGTH,(char*)buf); if((l.data[LUMP_DATA_LEN]!=′M′)‖(tmp_in[LUMP_DATA_LEN]!=′M′)) { WBuf.Format(_L(″After to64:%d,%d″),l.data[LUMP_DATA_LEN],tmp_in[LUMP_DATA_LEN]); ShowDebug(WBuf); } strcat((char*)buf,″\r\n″); return buf; } /*取base64,加密的串,在将其写至文件之前进行非base64和 <!-- SIPO <DP n="85"> --> <dp n="d85"/> *非加密处理。 *基本行在被写成lumpIO_fgets时是一集总决。 */ int PatClient∷lumpIO_fputs(char*str,struct lumpIO*lio) { struct lump 1; unsigned char tmp_out[LUMP_DATA_LEN+16]; unsigned char tmp_hex[256]; TBuf<256>WBuf; FILE*f=lio->f; if(feof(f)‖ferror(f)) return EOF; // from64_init(); int used,from; if((from=from64(str,strlen(str),&tmp_out[0],&used))<0) return-1; l.length=tmp_out[0];//length isn′t encrypted so read it now Decrypt(&lio->ctx_dec,(unsigned char*)&l.data[0],&tmp_out[2], LUMP_DATA_LEN); l.data[l.length]=0; WBuf.Format(_L(″After decrypt%s″),&l.data[0]); ParentAppUi->AddLine(WBuf); int ret=fwrite(&l.data[0],sizeof(char),l.length,f); if(ret<0) return EOF; return ret; }
Claims (22)
1.一种鉴别移动设备以便将数据从包括至少一个计算机的计算机系统传输至移动设备的方法,其特征在于下列步骤:
(I)在计算机系统中生成代码字,并将该代码字传给所述设备的预定地址;
(II)在所述设备中接收上述代码字;
(III)根据接收到的代码字按预定的方式生成代码消息;
(IV)将所述代码消息从上述设备传给计算机系统;
(V)用上述代码字检查代码消息;以及
(VI)若计算机系统验证了代码消息,则将数据从计算机系统传送给所述移动设备。
2.如权利要求1的方法,其特征在于,步骤(III)包括下列步骤:用唯一加密密钥对接收到的代码字进行加密。
3.如权利要求1-2的任何一项的方法,其特征在于这样的步骤:通过将鉴别请求传给计算机系统而从移动设备启动鉴别。
4.如权利要求1-2的任何一项的方法,其特征在于这样的步骤:从计算机系统启动鉴别以便将诸如电子邮件之类的数据传送给移动设备。
5.如权利要求4的方法,其特征在于,自动地进行步骤(I)-(VI)。
6.如权利要求1-5的任何一项的方法,其特征在于,在步骤(IV)中连同发送者地址一起传送代码消息,并且,与步骤(V)和步骤(VI)相关联地抽取发送者地址,并且在步骤(VI)中将数据传给该地址。
7.如权利要求1-6的任何一项的方法,其特征在于,在代码消息传输步骤(IV)中使用超文本传输协议(HTTP)或简单邮件传输协议(SMTP)。
8.如权利要求1-6的任何一项的方法,其特征在于,在步骤(I)中生成一随机代码字。
9.一种包括移动通信设备以及包含至少一个计算机在内的计算机系统的系统,用于鉴别移动设备以便进行从计算机系统向该移动设备的数据传输,所述系统的特征在于,
所述计算机系统包括:
-用于生成代码字并将该代码字传给所述设备的预定地址的装置;
-用上述代码字检查代码消息的装置;以及
-用于当计算机系统验证了代码消息时将数据从计算机系统传送给所述设备的装置;
所述移动设备包括:
-接收上述代码字的装置;
-根据接收到的代码字按预定的方式生成代码消息的装置;
-将所述代码消息传给计算机系统的装置。
10.如权利要求9的系统,其特征在于,所述用于生成代码消息的装置包括用唯一加密密钥对代码字进行加密的装置。
11.如权利要求9-10的任何一项的系统,其特征在于,所述设备包括用于启动鉴别过程的装置。
12.如权利要求9-11的任何一项的系统,其特征在于,所述计算机系统包括用于当计算机系统接收到了要传送给所述设备的数据时则自动启动鉴别过程的装置。
13.如权利要求9-12的任何一项的系统,其特征在于,所述用于将代码消息传送给计算机系统的装置使用了超文本传输协议(HTTP)或简单邮件传输协议(SMTP)。
14.如权利要求9-13的任何一项的系统,其特征在于,所述计算机系统包括用于随机产生代码字的装置。
15.在一个系统中,用于鉴别移动设备以便从计算机系统进行数据传输,所述系统包括:
一计算机系统:该系统具有:用于生成代码字并将该代码字传给所述设备的预定地址的装置;用上述代码字检查代码消息的装置;以及,用于当计算机系统验证了代码消息时则将数据从计算机系统传送给所述设备的装置;
所述移动通信设备的特征在于:
接收上述代码字的装置;
根据接收到的代码字按预定的方式生成代码消息的装置;以及
将所述代码消息传给计算机系统的装置。
16.在一个系统中,用于鉴别移动设备以便从计算机系统进行数
据传输,所述系统包括:
一个移动通信设备,该设备具有:接收上述代码字的装置;根据接收到的代码字按预定的方式生成代码消息的装置;以及,将所述代码消息传送给计算机系统的装置;
所述计算机包括至少一个计算机,其特征在于:
用于生成代码字并将该代码字传送给所述设备的预定地址的装置;
用上述代码字检查代码消息的装置;以及
当计算机系统验证了代码消息时则将数据从计算机系统传给所述设备的装置。
17.一种用于鉴别移动设备的计算机程序产品,它包括计算机可读代码以便使移动通信设备执行下列步骤:
(I)接收代码字并至少暂时存储该代码字;
(II)根据该代码字按预定的方式生成代码消息;以及
(III)将所述代码消息从移动设备传给计算机系统以便被鉴别,从而进行来自计算机系统的数据传输。
18.一种用于鉴别移动设备的计算机程序产品,它包括计算机可读代码以便使计算机执行下列步骤:
(I)生成代码字;
(II)启动将该代码字传送给所述移动设备的预定地址;
(III)接收代码消息;
(IV)用上述代码字检查代码消息;
(V)当验证了代码消息时将数据传送给所述移动设备。
19.如权利要求18的计算机程序产品,其特征在于,它包括计算机可读代码以便使计算机抽取在步骤(III)中接收到的代码消息的发送者地址,并在步骤(V)中启动将数据传给该地址的传输。
20.如权利要求18-20中任何一项的计算机程序产品,其特征在于,它包括计算机可读代码以便使计算机在步骤(I)中产生一个随机代码字。
21.一种存储在数据载体上的计算机程序,该计算机程序能执行根据权利要求1、4、5、6或8中任何一项的方法中的计算机系统所执行的步骤。
22.一种存储在数据载体上的计算机程序,该计算机程序能执行根据权利要求1的方法中的设备所执行的步骤。
Applications Claiming Priority (2)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
SE9902746A SE514769C2 (sv) | 1999-07-16 | 1999-07-16 | Sätt och system för autentisering av en mobilkommunikationsanordning |
SE99027468 | 1999-07-16 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN1375173A true CN1375173A (zh) | 2002-10-16 |
CN1153501C CN1153501C (zh) | 2004-06-09 |
Family
ID=20416536
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CNB008130310A Expired - Fee Related CN1153501C (zh) | 1999-07-16 | 2000-07-04 | 用于鉴别移动通信设备的方法和系统 |
Country Status (6)
Country | Link |
---|---|
EP (1) | EP1195071A1 (zh) |
JP (1) | JP2003504773A (zh) |
CN (1) | CN1153501C (zh) |
AU (1) | AU6192200A (zh) |
SE (1) | SE514769C2 (zh) |
WO (1) | WO2001006805A1 (zh) |
Cited By (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN108920629A (zh) * | 2018-06-29 | 2018-11-30 | 郑州云海信息技术有限公司 | 一种文件系统的acl权限设置方法、装置、设备及介质 |
Families Citing this family (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
FR2842055B1 (fr) * | 2002-07-05 | 2004-12-24 | Nortel Networks Ltd | Procede pour controler l'acces a un systeme cellulaire de radiocommunication a travers un reseau local sans fil, et organe de controle pour la mise en oeuvre du procede |
US20070093259A1 (en) * | 2005-10-26 | 2007-04-26 | Hyatt Edward C | Methods, systems, and computer program products for secured access to list server information via SMS messaging |
US8943560B2 (en) | 2008-05-28 | 2015-01-27 | Microsoft Corporation | Techniques to provision and manage a digital telephone to authenticate with a network |
Family Cites Families (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
SE503752C2 (sv) * | 1995-08-30 | 1996-08-26 | Sendit Ab | System och värdanordning för överföring av elektronisk post över ett mobiltelenät |
US5699428A (en) * | 1996-01-16 | 1997-12-16 | Symantec Corporation | System for automatic decryption of file data on a per-use basis and automatic re-encryption within context of multi-threaded operating system under which applications run in real-time |
US5736932A (en) * | 1996-07-03 | 1998-04-07 | At&T Corp | Security for controlled access systems |
JPH10215488A (ja) * | 1997-01-31 | 1998-08-11 | Nec Corp | 移動無線システムにおけるホストアクセス方法 |
ATE483204T1 (de) * | 1997-07-30 | 2010-10-15 | Visto Corp | System und verfahren zum globalen und sicheren zugriff auf vereinte information in einem rechnernetz |
-
1999
- 1999-07-16 SE SE9902746A patent/SE514769C2/sv not_active IP Right Cessation
-
2000
- 2000-07-04 AU AU61922/00A patent/AU6192200A/en not_active Abandoned
- 2000-07-04 EP EP00948441A patent/EP1195071A1/en not_active Withdrawn
- 2000-07-04 JP JP2001510503A patent/JP2003504773A/ja not_active Withdrawn
- 2000-07-04 WO PCT/SE2000/001418 patent/WO2001006805A1/en not_active Application Discontinuation
- 2000-07-04 CN CNB008130310A patent/CN1153501C/zh not_active Expired - Fee Related
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN108920629A (zh) * | 2018-06-29 | 2018-11-30 | 郑州云海信息技术有限公司 | 一种文件系统的acl权限设置方法、装置、设备及介质 |
CN108920629B (zh) * | 2018-06-29 | 2021-10-26 | 郑州云海信息技术有限公司 | 一种文件系统的acl权限设置方法、装置、设备及介质 |
Also Published As
Publication number | Publication date |
---|---|
EP1195071A1 (en) | 2002-04-10 |
AU6192200A (en) | 2001-02-05 |
SE9902746L (sv) | 2001-01-17 |
CN1153501C (zh) | 2004-06-09 |
JP2003504773A (ja) | 2003-02-04 |
SE514769C2 (sv) | 2001-04-23 |
SE9902746D0 (sv) | 1999-07-16 |
WO2001006805A1 (en) | 2001-01-25 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US8819410B2 (en) | Private electronic information exchange | |
US6748529B2 (en) | Method and apparatus for effecting secure document format conversion | |
US7650500B2 (en) | Encryption communication system | |
US7360079B2 (en) | System and method for processing digital documents utilizing secure communications over a network | |
Sollins | Cascaded authentication. | |
JP4913044B2 (ja) | ネットワークを用いて送り側と受け側との間でデータを暗号化し移送する方法 | |
US20030163691A1 (en) | System and method for authenticating sessions and other transactions | |
EP0869652A2 (en) | Document delivery system | |
US8484472B2 (en) | System and method of filtering unsolicited messages | |
CA2383000A1 (en) | Solicited authentication of a specific user | |
WO2002102020A1 (en) | Transparent ssl proxy | |
CN101510877A (zh) | 单点登录方法和系统、通信装置 | |
CN101247407A (zh) | 网络认证服务系统和方法 | |
US20060101124A1 (en) | Method and apparatus for mass email transmission | |
WO2006089879A1 (en) | Mapping an encrypted https network packet to a specific url name and other data without decryption outside of a secure web server | |
CN103428077B (zh) | 一种安全收发邮件的方法和系统 | |
CN1451213A (zh) | 用于鉴别电子信息的系统和方法 | |
CN102209046A (zh) | 网络资源整合系统及方法 | |
CN109005194A (zh) | 基于kcp协议的无端口影子通信方法及计算机存储介质 | |
WO2007147031A2 (en) | Push type communications system | |
CN1153501C (zh) | 用于鉴别移动通信设备的方法和系统 | |
US20200220730A1 (en) | System and method for authenticating sender(s) of an electronic message transmitted over a telephony network | |
WO2000046952A1 (en) | Method for sending secure email via standard browser | |
EP2078395A2 (en) | Enhanced wireless short message service | |
CN118282626A (zh) | 基于量子密钥加密的电子邮件安全传输方法及系统 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
C10 | Entry into substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
C06 | Publication | ||
PB01 | Publication | ||
C10 | Entry into substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
C14 | Grant of patent or utility model | ||
GR01 | Patent grant | ||
C19 | Lapse of patent right due to non-payment of the annual fee | ||
CF01 | Termination of patent right due to non-payment of annual fee |