source: ogServer-Git/src/client.c

Last change on this file was 8cf0247, checked in by Jose M. Guisado <jguisado@…>, 12 months ago

client: increase software inventory buffer size

Large software inventory is truncated because it does not fit into the
existing buffer.

Software inventory response payload consists of a string with each
component delimited by '\n'. Large software inventories can consist of
more than 8192 bytes.

Avoid truncating any large software inventory by increasing the buffer
size where this string is stored.

  • Property mode set to 100644
File size: 22.3 KB
Line 
1/*
2 * Copyright (C) 2020-2021 Soleta Networks <info@soleta.eu>
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Affero General Public License as published by the
6 * Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 */
9
10#include "ogAdmServer.h"
11#include "cfg.h"
12#include "dbi.h"
13#include "utils.h"
14#include "list.h"
15#include "rest.h"
16#include "json.h"
17#include "schedule.h"
18#include <syslog.h>
19#include <sys/ioctl.h>
20#include <ifaddrs.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <jansson.h>
25#include <time.h>
26
27#define OG_LEGACY_OGAGENT_LOG_FILE "/opt/opengnsys/log/ogagent.log"
28#define OG_CLIENT_SESSION_EVENT_LOGIN "logged in"
29#define OG_CLIENT_SESSION_EVENT_LOGOUT "logged out"
30#define OG_CLIENT_SESSION_OS_LINUX "Linux"
31#define OG_CLIENT_SESSION_OS_WINDOWS "Windows"
32#define OG_CLIENT_SESSION_TIMEDATE_LEN 20
33
34static void og_status_session_log(const struct og_client *cli,
35                                  const char *type, const char* user,
36                                  const char *os)
37{
38        char date[OG_CLIENT_SESSION_TIMEDATE_LEN];
39        char client_ip[INET_ADDRSTRLEN];
40        time_t now;
41        FILE *fp;
42
43        time(&now);
44        strftime(date, OG_CLIENT_SESSION_TIMEDATE_LEN, "%FT%T", gmtime(&now));
45
46        inet_ntop(AF_INET, &(cli->addr.sin_addr), client_ip, INET_ADDRSTRLEN);
47
48        fp = fopen(OG_LEGACY_OGAGENT_LOG_FILE, "a");
49        if (fp) {
50                fprintf(fp, "%s: User %s: ip=%s, user=%s, lang=en, os=%s:%s.\n",
51                        date, type, client_ip, user, os, os);
52                fclose(fp);
53        }
54}
55
56static int og_status_session_start(struct og_client *cli, const char *user)
57{
58        switch (cli->status) {
59        case OG_CLIENT_STATUS_LINUX:
60                cli->status = OG_CLIENT_STATUS_LINUX_SESSION;
61                og_status_session_log(cli, OG_CLIENT_SESSION_EVENT_LOGIN, user,
62                                      OG_CLIENT_SESSION_OS_LINUX);
63                break;
64        case OG_CLIENT_STATUS_WIN:
65                cli->status = OG_CLIENT_STATUS_WIN_SESSION;
66                og_status_session_log(cli, OG_CLIENT_SESSION_EVENT_LOGIN, user,
67                                      OG_CLIENT_SESSION_OS_WINDOWS);
68                break;
69        default:
70                syslog(LOG_ERR, "%s:%d: invalid session start for status %d\n",
71                       __FILE__, __LINE__, cli->status);
72                return -1;
73        }
74        return 0;
75}
76
77static int og_status_session_stop(struct og_client *cli, const char *user)
78{
79        switch (cli->status) {
80        case OG_CLIENT_STATUS_WIN_SESSION:
81                cli->status = OG_CLIENT_STATUS_WIN;
82                og_status_session_log(cli, OG_CLIENT_SESSION_EVENT_LOGOUT, user,
83                                      OG_CLIENT_SESSION_OS_WINDOWS);
84                break;
85        case OG_CLIENT_STATUS_LINUX_SESSION:
86                cli->status = OG_CLIENT_STATUS_LINUX;
87                og_status_session_log(cli, OG_CLIENT_SESSION_EVENT_LOGOUT, user,
88                                      OG_CLIENT_SESSION_OS_LINUX);
89                break;
90        default:
91                syslog(LOG_ERR, "%s:%d: invalid session stop for status %d\n",
92                       __FILE__, __LINE__, cli->status);
93                return -1;
94        }
95        return 0;
96}
97
98static int og_resp_early_hints(struct og_client *cli, json_t *data)
99{
100        const char *event, *action, *user;
101        const char *key;
102        json_t *value;
103        int err = 0;
104
105        if (json_typeof(data) != JSON_OBJECT)
106                return -1;
107
108        json_object_foreach(data, key, value) {
109                if (!strcmp(key, "event")) {
110                        err = og_json_parse_string(value, &event);
111                        if (err < 0)
112                                return err;
113                } else if (!strcmp(key, "action")) {
114                        err = og_json_parse_string(value, &action);
115                        if (err < 0)
116                                return err;
117                } else if (!strcmp(key, "user")) {
118                        err = og_json_parse_string(value, &user);
119                        if (err < 0)
120                                return err;
121                }
122        }
123
124        syslog(LOG_INFO, "Received event %s %s %s\n", event, action, user);
125
126        if (strncmp(event, "session", strlen("session")))
127                return -1;
128
129        if (!strncmp(action, "start", strlen("start")))
130                return og_status_session_start(cli, user);
131        if (!strncmp(action, "stop", strlen("stop")))
132                return og_status_session_stop(cli, user);
133
134        syslog(LOG_ERR, "Invalid action for event %s %s %s\n", event, action, user);
135        return -1;
136}
137
138static int og_resp_probe(struct og_client *cli, json_t *data)
139{
140        const char *status = NULL;
141        const char *key;
142        uint32_t speed;
143        json_t *value;
144        int err = 0;
145
146        if (json_typeof(data) != JSON_OBJECT)
147                return -1;
148
149        json_object_foreach(data, key, value) {
150                if (!strcmp(key, "status")) {
151                        err = og_json_parse_string(value, &status);
152                        if (err < 0)
153                                return err;
154                } else if (!strcmp(key, "speed")) {
155                        err = og_json_parse_uint(value, &speed);
156                        if (err < 0)
157                                return err;
158                        cli->speed = speed;
159                }
160        }
161
162        if (!strcmp(status, "BSY"))
163                cli->status = OG_CLIENT_STATUS_BUSY;
164        else if (!strcmp(status, "OPG"))
165                cli->status = OG_CLIENT_STATUS_OGLIVE;
166        else if (!strcmp(status, "VDI"))
167                cli->status = OG_CLIENT_STATUS_VIRTUAL;
168
169        return status ? 0 : -1;
170}
171
172static int og_resp_shell_run(struct og_client *cli, json_t *data)
173{
174        const char *output = NULL;
175        const char *key;
176        json_t *value;
177        int err = -1;
178
179        if (json_typeof(data) != JSON_OBJECT)
180                return -1;
181
182        json_object_foreach(data, key, value) {
183                if (!strcmp(key, "out")) {
184                        err = og_json_parse_string(value, &output);
185                        if (err < 0)
186                                return err;
187                }
188        }
189
190        if (!output) {
191                syslog(LOG_ERR, "%s:%d: malformed json response\n",
192                       __FILE__, __LINE__);
193                return -1;
194        }
195
196        free((void *)cli->shell_output);
197        cli->shell_output = strdup(output);
198
199        return 0;
200}
201
202struct og_computer_legacy  {
203        char center[OG_DB_INT_MAXLEN + 1];
204        char id[OG_DB_INT_MAXLEN + 1];
205        char hardware[8192];
206};
207
208static int og_resp_hardware(json_t *data, struct og_client *cli)
209{
210        struct og_computer_legacy legacy = {};
211        struct og_computer computer = {};
212        const char *hardware = NULL;
213        struct og_dbi *dbi;
214        const char *key;
215        json_t *value;
216        int err = 0;
217        bool res;
218
219        if (json_typeof(data) != JSON_OBJECT)
220                return -1;
221
222        json_object_foreach(data, key, value) {
223                if (!strcmp(key, "hardware")) {
224                        err = og_json_parse_string(value, &hardware);
225                        if (err < 0)
226                                return -1;
227                }
228        }
229
230        if (!hardware) {
231                syslog(LOG_ERR, "malformed response json\n");
232                return -1;
233        }
234
235        dbi = og_dbi_open(&ogconfig.db);
236        if (!dbi) {
237                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
238                       __func__, __LINE__);
239                return -1;
240        }
241
242        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
243        if (err < 0) {
244                og_dbi_close(dbi);
245                return -1;
246        }
247
248        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
249        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
250        snprintf(legacy.hardware, sizeof(legacy.hardware), "%s", hardware);
251
252        res = actualizaHardware(dbi, legacy.hardware, legacy.id, computer.name,
253                                legacy.center);
254        og_dbi_close(dbi);
255
256        if (!res) {
257                syslog(LOG_ERR, "Problem updating client configuration\n");
258                return -1;
259        }
260
261        return 0;
262}
263
264struct og_software_legacy {
265        char software[32768];
266        char center[OG_DB_INT_MAXLEN + 1];
267        char part[OG_DB_SMALLINT_MAXLEN + 1];
268        char id[OG_DB_INT_MAXLEN + 1];
269};
270
271static int og_resp_software(json_t *data, struct og_client *cli)
272{
273        struct og_software_legacy legacy = {};
274        struct og_computer computer = {};
275        const char *partition = NULL;
276        const char *software = NULL;
277        struct og_dbi *dbi;
278        const char *key;
279        json_t *value;
280        int err = 0;
281        bool res;
282
283        if (json_typeof(data) != JSON_OBJECT)
284                return -1;
285
286        json_object_foreach(data, key, value) {
287                if (!strcmp(key, "software"))
288                        err = og_json_parse_string(value, &software);
289                else if (!strcmp(key, "partition"))
290                        err = og_json_parse_string(value, &partition);
291
292                if (err < 0)
293                        return -1;
294        }
295
296        if (!software || !partition) {
297                syslog(LOG_ERR, "malformed response json\n");
298                return -1;
299        }
300
301        dbi = og_dbi_open(&ogconfig.db);
302        if (!dbi) {
303                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
304                       __func__, __LINE__);
305                return -1;
306        }
307
308        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
309        if (err < 0) {
310                og_dbi_close(dbi);
311                return -1;
312        }
313
314        snprintf(legacy.software, sizeof(legacy.software), "%s", software);
315        snprintf(legacy.part, sizeof(legacy.part), "%s", partition);
316        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
317        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
318
319        res = actualizaSoftware(dbi, legacy.software, legacy.part, legacy.id,
320                                computer.name, legacy.center);
321        og_dbi_close(dbi);
322
323        if (!res) {
324                syslog(LOG_ERR, "Problem updating client configuration\n");
325                return -1;
326        }
327
328        return 0;
329}
330
331#define OG_PARAMS_RESP_REFRESH  (OG_PARAM_PART_DISK |           \
332                                 OG_PARAM_PART_NUMBER |         \
333                                 OG_PARAM_PART_CODE |           \
334                                 OG_PARAM_PART_FILESYSTEM |     \
335                                 OG_PARAM_PART_OS |             \
336                                 OG_PARAM_PART_SIZE |           \
337                                 OG_PARAM_PART_USED_SIZE)
338
339static int og_json_parse_partition_array(json_t *value,
340                                         struct og_partition *partitions)
341{
342        json_t *element;
343        int i, err;
344
345        if (json_typeof(value) != JSON_ARRAY)
346                return -1;
347
348        for (i = 0; i < json_array_size(value) && i < OG_PARTITION_MAX; i++) {
349                element = json_array_get(value, i);
350
351                err = og_json_parse_partition(element, &partitions[i],
352                                              OG_PARAMS_RESP_REFRESH);
353                if (err < 0)
354                        return err;
355        }
356
357        return 0;
358}
359
360static int og_dbi_queue_autorun(uint32_t computer_id, uint32_t proc_id)
361{
362        struct og_task dummy_task = {
363                .scope          = computer_id,
364                .type_scope     = AMBITO_ORDENADORES,
365                .procedure_id   = proc_id,
366        };
367        struct og_dbi *dbi;
368
369        dbi = og_dbi_open(&ogconfig.db);
370        if (!dbi) {
371                syslog(LOG_ERR, "cannot open connection database "
372                                "(%s:%d)\n", __func__, __LINE__);
373                return -1;
374        }
375        if (og_dbi_queue_procedure(dbi, &dummy_task)) {
376                og_dbi_close(dbi);
377                return -1;
378        }
379        og_dbi_close(dbi);
380
381        return 0;
382}
383
384static int og_resp_refresh(json_t *data, struct og_client *cli)
385{
386        struct og_partition partitions[OG_PARTITION_MAX] = {};
387        struct og_partition disks[OG_DISK_MAX] = {};
388        const char *serial_number = NULL;
389        struct og_computer computer = {};
390        const char *status = NULL;
391        char cfg[4096] = {};
392        struct og_dbi *dbi;
393        uint32_t link = 0;
394        const char *key;
395        unsigned int i;
396        json_t *value;
397        int err = 0;
398        bool res;
399
400        if (json_typeof(data) != JSON_OBJECT)
401                return -1;
402
403        json_object_foreach(data, key, value) {
404                if (!strcmp(key, "disk_setup")) {
405                        err = og_json_parse_partition_array(value, disks);
406                } else if (!strcmp(key, "partition_setup")) {
407                        err = og_json_parse_partition_array(value, partitions);
408                } else if (!strcmp(key, "serial_number")) {
409                        err = og_json_parse_string(value, &serial_number);
410                } else if (!strcmp(key, "status")) {
411                        err = og_json_parse_string(value, &status);
412                } else if (!strcmp(key, "link")) {
413                        err = og_json_parse_uint(value, &link);
414                }
415
416                if (err < 0)
417                        return err;
418        }
419
420        if (link)
421                cli->speed = link;
422
423        if (status) {
424                if (!strncmp(status, "LINUX", strlen("LINUX"))) {
425                        cli->status = OG_CLIENT_STATUS_LINUX;
426                } else if (!strncmp(status, "WIN", strlen("WIN"))) {
427                        cli->status = OG_CLIENT_STATUS_WIN;
428                }
429                return 0;
430        }
431
432        if (strlen(serial_number) > 0)
433                snprintf(cfg, sizeof(cfg), "ser=%s\n", serial_number);
434
435        for (i = 0; i < OG_DISK_MAX; i++) {
436                if (!disks[i].disk || !disks[i].number ||
437                    !disks[i].code || !disks[i].filesystem ||
438                    !disks[i].os || !disks[i].size ||
439                    !disks[i].used_size)
440                        continue;
441
442                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
443                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\tdtype=%s\n",
444                         disks[i].disk, disks[i].number,
445                         disks[i].code, disks[i].filesystem,
446                         disks[i].os, disks[i].size,
447                         disks[i].used_size, disks[i].disk_type);
448        }
449
450        for (i = 0; i < OG_PARTITION_MAX; i++) {
451                if (!partitions[i].disk || !partitions[i].number ||
452                    !partitions[i].code || !partitions[i].filesystem ||
453                    !partitions[i].os || !partitions[i].size ||
454                    !partitions[i].used_size)
455                        continue;
456
457                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
458                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
459                         partitions[i].disk, partitions[i].number,
460                         partitions[i].code, partitions[i].filesystem,
461                         partitions[i].os, partitions[i].size,
462                         partitions[i].used_size);
463        }
464
465        dbi = og_dbi_open(&ogconfig.db);
466        if (!dbi) {
467                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
468                                  __func__, __LINE__);
469                return -1;
470        }
471
472        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
473        if (err < 0) {
474                og_dbi_close(dbi);
475                return -1;
476        }
477
478        res = actualizaConfiguracion(dbi, cfg, computer.id);
479        og_dbi_close(dbi);
480
481        if (!res) {
482                syslog(LOG_ERR, "Problem updating client configuration\n");
483                return -1;
484        }
485
486        if (!cli->autorun && computer.procedure_id) {
487                cli->autorun = true;
488
489                if (og_dbi_queue_autorun(computer.id, computer.procedure_id))
490                        return -1;
491        }
492
493        return 0;
494}
495
496static int update_image_info(struct og_dbi *dbi, const char *image_id,
497                             const char *clonator, const char *compressor,
498                             const char *filesystem, const uint64_t datasize)
499{
500        const char *msglog;
501        dbi_result result;
502
503        result = dbi_conn_queryf(dbi->conn,
504                "UPDATE imagenes"
505                "   SET clonator='%s', compressor='%s',"
506                "       filesystem='%s', datasize=%lld"
507                " WHERE idimagen=%s", clonator, compressor, filesystem,
508                datasize, image_id);
509
510        if (!result) {
511                dbi_conn_error(dbi->conn, &msglog);
512                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
513                       __func__, __LINE__, msglog);
514                return -1;
515        }
516        dbi_result_free(result);
517
518        return 0;
519}
520
521static int og_resp_image_create(json_t *data, struct og_client *cli)
522{
523        struct og_software_legacy soft_legacy;
524        struct og_image_legacy img_legacy;
525        struct og_computer computer = {};
526        const char *compressor = NULL;
527        const char *filesystem = NULL;
528        const char *partition = NULL;
529        const char *software = NULL;
530        const char *image_id = NULL;
531        const char *clonator = NULL;
532        const char *disk = NULL;
533        const char *code = NULL;
534        const char *name = NULL;
535        const char *repo = NULL;
536        uint64_t datasize = 0;
537        struct og_dbi *dbi;
538        const char *key;
539        json_t *value;
540        int err = 0;
541        bool res;
542
543        if (json_typeof(data) != JSON_OBJECT)
544                return -1;
545
546        json_object_foreach(data, key, value) {
547                if (!strcmp(key, "software"))
548                        err = og_json_parse_string(value, &software);
549                else if (!strcmp(key, "partition"))
550                        err = og_json_parse_string(value, &partition);
551                else if (!strcmp(key, "disk"))
552                        err = og_json_parse_string(value, &disk);
553                else if (!strcmp(key, "code"))
554                        err = og_json_parse_string(value, &code);
555                else if (!strcmp(key, "id"))
556                        err = og_json_parse_string(value, &image_id);
557                else if (!strcmp(key, "name"))
558                        err = og_json_parse_string(value, &name);
559                else if (!strcmp(key, "repository"))
560                        err = og_json_parse_string(value, &repo);
561                else if (!strcmp(key, "clonator"))
562                        err = og_json_parse_string(value, &clonator);
563                else if (!strcmp(key, "compressor"))
564                        err = og_json_parse_string(value, &compressor);
565                else if (!strcmp(key, "filesystem"))
566                        err = og_json_parse_string(value, &filesystem);
567                else if (!strcmp(key, "datasize"))
568                        err = og_json_parse_uint64(value, &datasize);
569
570                if (err < 0)
571                        return err;
572        }
573
574        if (!software || !partition || !disk || !code || !image_id || !name ||
575            !repo || !clonator || !compressor || !filesystem || !datasize) {
576                syslog(LOG_ERR, "malformed response json\n");
577                return -1;
578        }
579
580        dbi = og_dbi_open(&ogconfig.db);
581        if (!dbi) {
582                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
583                       __func__, __LINE__);
584                return -1;
585        }
586
587        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
588        if (err < 0) {
589                og_dbi_close(dbi);
590                return -1;
591        }
592
593        snprintf(soft_legacy.center, sizeof(soft_legacy.center), "%d",
594                 computer.center);
595        snprintf(soft_legacy.software, sizeof(soft_legacy.software), "%s",
596                 software);
597        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
598                 image_id);
599        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
600        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
601        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
602        snprintf(img_legacy.code, sizeof(img_legacy.code), "%s", code);
603        snprintf(img_legacy.name, sizeof(img_legacy.name), "%s", name);
604        snprintf(img_legacy.repo, sizeof(img_legacy.repo), "%s", repo);
605
606        res = actualizaSoftware(dbi,
607                                soft_legacy.software,
608                                img_legacy.part,
609                                soft_legacy.id,
610                                computer.name,
611                                soft_legacy.center);
612        if (!res) {
613                og_dbi_close(dbi);
614                syslog(LOG_ERR, "Problem updating client configuration\n");
615                return -1;
616        }
617
618        res = actualizaCreacionImagen(dbi,
619                                      img_legacy.image_id,
620                                      img_legacy.disk,
621                                      img_legacy.part,
622                                      img_legacy.code,
623                                      img_legacy.repo,
624                                      soft_legacy.id);
625        if (!res) {
626                og_dbi_close(dbi);
627                syslog(LOG_ERR, "Problem updating client configuration\n");
628                return -1;
629        }
630
631        res = update_image_info(dbi, image_id, clonator, compressor,
632                                filesystem, datasize);
633        og_dbi_close(dbi);
634
635        if (res) {
636                syslog(LOG_ERR, "Problem updating image info\n");
637                return -1;
638        }
639
640        return 0;
641}
642
643static int og_resp_image_restore(json_t *data, struct og_client *cli)
644{
645        struct og_software_legacy soft_legacy;
646        struct og_image_legacy img_legacy;
647        struct og_computer computer = {};
648        const char *partition = NULL;
649        const char *image_id = NULL;
650        const char *disk = NULL;
651        const char *msglog;
652        struct og_dbi *dbi;
653        dbi_result result;
654        const char *key;
655        json_t *value;
656        int err = 0;
657
658        if (json_typeof(data) != JSON_OBJECT)
659                return -1;
660
661        json_object_foreach(data, key, value) {
662                if (!strcmp(key, "partition"))
663                        err = og_json_parse_string(value, &partition);
664                else if (!strcmp(key, "disk"))
665                        err = og_json_parse_string(value, &disk);
666                else if (!strcmp(key, "image_id"))
667                        err = og_json_parse_string(value, &image_id);
668
669                if (err < 0)
670                        return err;
671        }
672
673        if (!partition || !disk || !image_id) {
674                syslog(LOG_ERR, "malformed response json\n");
675                return -1;
676        }
677
678        dbi = og_dbi_open(&ogconfig.db);
679        if (!dbi) {
680                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
681                       __func__, __LINE__);
682                return -1;
683        }
684
685        result = dbi_conn_queryf(dbi->conn,
686                                 "SELECT idperfilsoft FROM imagenes "
687                                 " WHERE idimagen='%s'", image_id);
688        if (!result) {
689                og_dbi_close(dbi);
690                syslog(LOG_ERR, "failed to query database\n");
691                return -1;
692        }
693        if (!dbi_result_next_row(result)) {
694                dbi_result_free(result);
695                og_dbi_close(dbi);
696                syslog(LOG_ERR, "software profile does not exist in database\n");
697                return -1;
698        }
699        snprintf(img_legacy.software_id, sizeof(img_legacy.software_id),
700                 "%d", dbi_result_get_uint(result, "idperfilsoft"));
701        dbi_result_free(result);
702
703        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
704        if (err < 0) {
705                og_dbi_close(dbi);
706                return -1;
707        }
708
709        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
710                 image_id);
711        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
712        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
713        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
714
715        result = dbi_conn_queryf(dbi->conn,
716                                 "UPDATE ordenadores_particiones"
717                                 "   SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW(),"
718                                 "       revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
719                                 "       idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)"
720                                 " WHERE idordenador=%s AND numdisk=%s AND numpar=%s",
721                                 img_legacy.image_id, img_legacy.software_id,
722                                 img_legacy.image_id, img_legacy.software_id,
723                                 soft_legacy.id, img_legacy.disk, img_legacy.part);
724        if (!result) {
725                dbi_conn_error(dbi->conn, &msglog);
726                syslog(LOG_ERR, "failed to update database (%s:%d) %s\n",
727                       __func__, __LINE__, msglog);
728                og_dbi_close(dbi);
729                return -1;
730        }
731        dbi_result_free(result);
732        og_dbi_close(dbi);
733
734        return 0;
735}
736
737static int og_agent_http_response_code(const char *buf)
738{
739        if (!strncmp(buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) {
740                return 200;
741        } else if (!strncmp(buf, "HTTP/1.0 202 Accepted",
742                            strlen("HTTP/1.0 202 Accepted"))) {
743                return 202;
744        } else if (!strncmp(buf, "HTTP/1.0 400 Bad Request",
745                            strlen("HTTP/1.0 400 Bad Request"))) {
746                return 400;
747        } else if (!strncmp(buf, "HTTP/1.0 500 Internal Server Error",
748                            strlen("HTTP/1.0 500 Internal Server Error"))) {
749                return 500;
750        } else if (!strncmp(buf, "HTTP/1.0 503 Service Unavailable",
751                            strlen("HTTP/1.0 503 Service Unavailable"))) {
752                return 503;
753        } else if (!strncmp(buf, "HTTP/1.0 103 Early Hints",
754                            strlen("HTTP/1.0 103 Early Hints"))) {
755                return 103;
756        }
757
758        return -1;
759}
760
761int og_agent_state_process_response(struct og_client *cli)
762{
763        int ret, err = -1, code;
764        json_error_t json_err;
765        bool success;
766        json_t *root;
767        char *body;
768
769        code = og_agent_http_response_code(cli->buf);
770        switch (code) {
771        case 103:
772        case 200:
773                ret = 0;
774                success = true;
775                break;
776        case 202:
777                ret = 1;
778                success = true;
779                break;
780        case 400:
781                ret = -1;
782                success = false;
783                syslog(LOG_ERR, "Client %s:%hu reports malformed HTTP request from server\n",
784                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
785                break;
786        case 500:
787                ret = 0;
788                success = false;
789                cli->last_cmd = OG_CMD_UNSPEC;
790                syslog(LOG_ERR, "Client %s:%hu reports failure to process command\n",
791                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
792                /* ... cancel pending actions related to this task for this client here */
793                break;
794        case 503:
795                ret = 1;
796                success = false;
797                syslog(LOG_ERR, "Client %s:%hu is busy to process command\n",
798                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
799                break;
800        default:
801                ret = -1;
802                success = false;
803                syslog(LOG_ERR, "Client %s:%hu reports unknown HTTP response code\n",
804                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
805                break;
806        }
807
808        if (success)
809                cli->last_cmd_result = OG_SUCCESS;
810        else
811                cli->last_cmd_result = OG_FAILURE;
812
813        if (code != 200 && code != 103) {
814                og_dbi_update_action(cli->last_cmd_id, success);
815                cli->last_cmd_id = 0;
816                return ret;
817        }
818
819        if (!cli->content_length) {
820                og_dbi_update_action(cli->last_cmd_id, true);
821                cli->last_cmd_id = 0;
822                cli->last_cmd = OG_CMD_UNSPEC;
823                return 0;
824        }
825
826        body = strstr(cli->buf, "\r\n\r\n") + 4;
827
828        root = json_loads(body, 0, &json_err);
829        if (!root) {
830                syslog(LOG_ERR, "%s:%d: malformed json line %d: %s\n",
831                       __FILE__, __LINE__, json_err.line, json_err.text);
832                return -1;
833        }
834
835        if (code == 103) {
836                err = og_resp_early_hints(cli, root);
837                json_decref(root);
838                return err;
839        }
840
841        switch (cli->last_cmd) {
842        case OG_CMD_PROBE:
843                err = og_resp_probe(cli, root);
844                break;
845        case OG_CMD_SHELL_RUN:
846                err = og_resp_shell_run(cli, root);
847                break;
848        case OG_CMD_HARDWARE:
849                err = og_resp_hardware(root, cli);
850                break;
851        case OG_CMD_SOFTWARE:
852                err = og_resp_software(root, cli);
853                break;
854        case OG_CMD_REFRESH:
855                err = og_resp_refresh(root, cli);
856                break;
857        case OG_CMD_SETUP:
858                err = og_resp_refresh(root, cli);
859                break;
860        case OG_CMD_IMAGE_CREATE:
861                err = og_resp_image_create(root, cli);
862                break;
863        case OG_CMD_IMAGE_RESTORE:
864                err = og_resp_image_restore(root, cli);
865                break;
866        default:
867                err = -1;
868                break;
869        }
870
871        json_decref(root);
872
873        if (err < 0) {
874                err = 0;
875                success = false;
876                cli->last_cmd_result = OG_FAILURE;
877                /* ... cancel pending actions related to this task for this client here */
878        }
879
880        og_dbi_update_action(cli->last_cmd_id, success);
881        cli->last_cmd_id = 0;
882        cli->last_cmd = OG_CMD_UNSPEC;
883
884        return err;
885}
Note: See TracBrowser for help on using the repository browser.