gpgsm --verify does now work like gpg including the
[gnupg.git] / sm / server.c
1 /* server.c - Server mode and main entry point 
2  *      Copyright (C) 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <unistd.h>
28
29 #include "gpgsm.h"
30 #include "../assuan/assuan.h"
31
32 #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
33
34
35 /*  RECIPIENT <userID>
36
37   Set the recipient for the encryption.  <userID> should be the
38   internal representation of the key; the server may accept any other
39   way of specification [we will support this].  If this is a valid and
40   trusted recipient the server does respond with OK, otherwise the
41   return is an ERR with the reason why the recipient can't be used,
42   the encryption will then not be done for this recipient.  IF the
43   policy is not to encrypt at all if not all recipients are valid, the
44   client has to take care of this.  All RECIPIENT commands are
45   cumulative until a RESET or ENCRYPT command.  */
46 static int 
47 cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
48 {
49   
50
51   return set_error (Not_Implemented, "fixme");
52 }
53
54
55 /* ENCRYPT [armor]
56
57   Do the actual encryption process. Takes the plaintext from the INPUT
58   command, writes to the ciphertext to the file descriptor set with
59   the OUTPUT command, take the recipients form all the recipients set
60   so far.  If this command fails the clients should try to delete all
61   output currently done or otherwise mark it as invalid.  GPGSM does
62   ensure that there won't be any security problem with leftover data
63   on the output in this case.
64
65   This command should in general not fail, as all necessary checks
66   have been done while setting the recipients.  The input and output
67   pipes are closed.
68
69   The optional armor parameter may be used to request base64 encoded
70   output.  */
71 static int 
72 cmd_encrypt (ASSUAN_CONTEXT ctx, char *line)
73 {
74   
75
76   return set_error (Not_Implemented, "fixme");
77 }
78
79 /* DECRYPT
80
81   This performs the decrypt operation after doing some check on the
82   internal state. (e.g. that only needed data has been set).  Because
83   it utilises the GPG-Agent for the session key decryption, there is
84   no need to ask the client for a protecting passphrase - GpgAgent
85   does take care of this but requesting this from the user. */
86 static int 
87 cmd_decrypt (ASSUAN_CONTEXT ctx, char *line)
88 {
89   
90
91   return set_error (Not_Implemented, "fixme");
92 }
93
94
95 /* VERIFY
96
97   This does a verify operation on the message send to the input-FD.
98   The result is written out using status lines.  If an output FD was
99   given, the signed text will be written to that.
100   
101   If the signature is a detached one, the server will inquire about
102   the signed material and the client must provide it.
103   */
104 static int 
105 cmd_verify (ASSUAN_CONTEXT ctx, char *line)
106 {
107   int fd = assuan_get_input_fd (ctx);
108
109   if (fd == -1)
110     return set_error (No_Input, NULL);
111
112   gpgsm_verify (fd, -1);
113
114   return 0;
115 }
116
117
118 /* SIGN
119
120    FIXME */
121 static int 
122 cmd_sign (ASSUAN_CONTEXT ctx, char *line)
123 {
124   
125
126   return set_error (Not_Implemented, "fixme");
127 }
128
129
130 /* IMPORT
131
132   Import the certificates read form the input-fd, return status
133   message for each imported one.  The import checks the validity of
134   the certificate but not of the path.  It is possible to import
135   expired certificates.  */
136 static int 
137 cmd_import (ASSUAN_CONTEXT ctx, char *line)
138 {
139   int fd = assuan_get_input_fd (ctx);
140
141   if (fd == -1)
142     return set_error (No_Input, NULL);
143
144   gpgsm_import (fd);
145
146   return 0;
147 }
148
149
150
151 \f
152 /* Tell the assuan library about our commands */
153 static int
154 register_commands (ASSUAN_CONTEXT ctx)
155 {
156   static struct {
157     const char *name;
158     int cmd_id;
159     int (*handler)(ASSUAN_CONTEXT, char *line);
160   } table[] = {
161     { "RECIPIENT",  0,  cmd_recipient },
162     { "ENCRYPT",    0,  cmd_encrypt },
163     { "DECRYPT",    0,  cmd_decrypt },
164     { "VERIFY",     0,  cmd_verify },
165     { "SIGN",       0,  cmd_sign },
166     { "IMPORT",     0,  cmd_import },
167     { "",     ASSUAN_CMD_INPUT, NULL }, 
168     { "",     ASSUAN_CMD_OUTPUT, NULL }, 
169     { NULL }
170   };
171   int i, j, rc;
172
173   for (i=j=0; table[i].name; i++)
174     {
175       rc = assuan_register_command (ctx,
176                                     table[i].cmd_id? table[i].cmd_id
177                                                    : (ASSUAN_CMD_USER + j++),
178                                     table[i].name, table[i].handler);
179       if (rc)
180         return rc;
181     } 
182   return 0;
183 }
184
185 /* Startup the server */
186 void
187 gpgsm_server (void)
188 {
189   int rc;
190   int filedes[2];
191   ASSUAN_CONTEXT ctx;
192
193   /* For now we use a simple pipe based server so that we can work
194      from scripts.  We will later add options to run as a daemon and
195      wait for requests on a Unix domain socket */
196   filedes[0] = 0;
197   filedes[1] = 1;
198   rc = assuan_init_pipe_server (&ctx, filedes);
199   if (rc)
200     {
201       log_error ("failed to initialize the server: %s\n",
202                  assuan_strerror(rc));
203       gpgsm_exit (2);
204     }
205   rc = register_commands (ctx);
206   if (rc)
207     {
208       log_error ("failed to the register commands with Assuan: %s\n",
209                  assuan_strerror(rc));
210       gpgsm_exit (2);
211     }
212
213   log_info ("Assuan started\n");
214   for (;;)
215     {
216       rc = assuan_accept (ctx);
217       if (rc == -1)
218         {
219           log_info ("Assuan terminated\n");
220           break;
221         }
222       else if (rc)
223         {
224           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
225           break;
226         }
227       
228       rc = assuan_process (ctx);
229       if (rc)
230         {
231           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
232           continue;
233         }
234     }
235
236
237   assuan_deinit_pipe_server (ctx);
238 }
239
240
241
242
243
244
245