source: ogServer-Git/sources/client.c @ 1a406b2

Last change on this file since 1a406b2 was 9c8e5c7, checked in by OpenGnSys Support Team <soporte-og@…>, 4 years ago

#941 Move OG_COMPUTER_NAME_MAXLEN to dbi.h

This parameter is actually a database related parameter so now it is renamed to
OG_DB_COMPUTER_NAME_MAXLEN.

  • Property mode set to 100644
File size: 16.5 KB
Line 
1/*
2 * Copyright (C) 2020 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, version 3.
7 */
8
9#include "ogAdmServer.h"
10#include "dbi.h"
11#include "utils.h"
12#include "list.h"
13#include "rest.h"
14#include "json.h"
15#include "schedule.h"
16#include <syslog.h>
17#include <sys/ioctl.h>
18#include <ifaddrs.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22#include <jansson.h>
23#include <time.h>
24
25struct og_computer {
26        unsigned int    id;
27        unsigned int    center;
28        unsigned int    room;
29        char            name[OG_DB_COMPUTER_NAME_MAXLEN + 1];
30        unsigned int    procedure_id;
31};
32
33static int og_dbi_get_computer_info(struct og_computer *computer,
34                                    struct in_addr addr)
35{
36        const char *msglog;
37        struct og_dbi *dbi;
38        dbi_result result;
39
40        dbi = og_dbi_open(&dbi_config);
41        if (!dbi) {
42                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
43                       __func__, __LINE__);
44                return -1;
45        }
46        result = dbi_conn_queryf(dbi->conn,
47                                 "SELECT ordenadores.idordenador,"
48                                 "       ordenadores.nombreordenador,"
49                                 "       ordenadores.idaula,"
50                                 "       ordenadores.idproautoexec,"
51                                 "       centros.idcentro FROM ordenadores "
52                                 "INNER JOIN aulas ON aulas.idaula=ordenadores.idaula "
53                                 "INNER JOIN centros ON centros.idcentro=aulas.idcentro "
54                                 "WHERE ordenadores.ip='%s'", inet_ntoa(addr));
55        if (!result) {
56                dbi_conn_error(dbi->conn, &msglog);
57                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
58                       __func__, __LINE__, msglog);
59                og_dbi_close(dbi);
60                return -1;
61        }
62        if (!dbi_result_next_row(result)) {
63                syslog(LOG_ERR, "client does not exist in database (%s:%d)\n",
64                       __func__, __LINE__);
65                dbi_result_free(result);
66                og_dbi_close(dbi);
67                return -1;
68        }
69
70        computer->id = dbi_result_get_uint(result, "idordenador");
71        computer->center = dbi_result_get_uint(result, "idcentro");
72        computer->room = dbi_result_get_uint(result, "idaula");
73        computer->procedure_id = dbi_result_get_uint(result, "idproautoexec");
74        strncpy(computer->name,
75                dbi_result_get_string(result, "nombreordenador"),
76                OG_DB_COMPUTER_NAME_MAXLEN);
77
78        dbi_result_free(result);
79        og_dbi_close(dbi);
80
81        return 0;
82}
83
84static int og_resp_probe(struct og_client *cli, json_t *data)
85{
86        const char *status = NULL;
87        const char *key;
88        json_t *value;
89        int err = 0;
90
91        if (json_typeof(data) != JSON_OBJECT)
92                return -1;
93
94        json_object_foreach(data, key, value) {
95                if (!strcmp(key, "status")) {
96                        err = og_json_parse_string(value, &status);
97                        if (err < 0)
98                                return err;
99                } else {
100                        return -1;
101                }
102        }
103
104        if (!strcmp(status, "BSY"))
105                cli->status = OG_CLIENT_STATUS_BUSY;
106        else if (!strcmp(status, "OPG"))
107                cli->status = OG_CLIENT_STATUS_OGLIVE;
108
109        return status ? 0 : -1;
110}
111
112static int og_resp_shell_run(struct og_client *cli, json_t *data)
113{
114        const char *output = NULL;
115        char filename[4096];
116        const char *key;
117        json_t *value;
118        int err = -1;
119        FILE *file;
120
121        if (json_typeof(data) != JSON_OBJECT)
122                return -1;
123
124        json_object_foreach(data, key, value) {
125                if (!strcmp(key, "out")) {
126                        err = og_json_parse_string(value, &output);
127                        if (err < 0)
128                                return err;
129                } else {
130                        return -1;
131                }
132        }
133
134        if (!output) {
135                syslog(LOG_ERR, "%s:%d: malformed json response\n",
136                       __FILE__, __LINE__);
137                return -1;
138        }
139
140        sprintf(filename, "/tmp/_Seconsola_%s", inet_ntoa(cli->addr.sin_addr));
141        file = fopen(filename, "wt");
142        if (!file) {
143                syslog(LOG_ERR, "cannot open file %s: %s\n",
144                       filename, strerror(errno));
145                return -1;
146        }
147
148        fprintf(file, "%s", output);
149        fclose(file);
150
151        return 0;
152}
153
154struct og_computer_legacy  {
155        char center[OG_DB_INT_MAXLEN + 1];
156        char id[OG_DB_INT_MAXLEN + 1];
157        char hardware[8192];
158};
159
160static int og_resp_hardware(json_t *data, struct og_client *cli)
161{
162        struct og_computer_legacy legacy = {};
163        const char *hardware = NULL;
164        struct og_computer computer;
165        struct og_dbi *dbi;
166        const char *key;
167        json_t *value;
168        int err = 0;
169        bool res;
170
171        if (json_typeof(data) != JSON_OBJECT)
172                return -1;
173
174        json_object_foreach(data, key, value) {
175                if (!strcmp(key, "hardware")) {
176                        err = og_json_parse_string(value, &hardware);
177                        if (err < 0)
178                                return -1;
179                } else {
180                        return -1;
181                }
182        }
183
184        if (!hardware) {
185                syslog(LOG_ERR, "malformed response json\n");
186                return -1;
187        }
188
189        err = og_dbi_get_computer_info(&computer, cli->addr.sin_addr);
190        if (err < 0)
191                return -1;
192
193        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
194        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
195        snprintf(legacy.hardware, sizeof(legacy.hardware), "%s", hardware);
196
197        dbi = og_dbi_open(&dbi_config);
198        if (!dbi) {
199                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
200                       __func__, __LINE__);
201                return -1;
202        }
203
204        res = actualizaHardware(dbi, legacy.hardware, legacy.id, computer.name,
205                                legacy.center);
206        og_dbi_close(dbi);
207
208        if (!res) {
209                syslog(LOG_ERR, "Problem updating client configuration\n");
210                return -1;
211        }
212
213        return 0;
214}
215
216struct og_software_legacy {
217        char software[8192];
218        char center[OG_DB_INT_MAXLEN + 1];
219        char part[OG_DB_SMALLINT_MAXLEN + 1];
220        char id[OG_DB_INT_MAXLEN + 1];
221};
222
223static int og_resp_software(json_t *data, struct og_client *cli)
224{
225        struct og_software_legacy legacy = {};
226        const char *partition = NULL;
227        const char *software = NULL;
228        struct og_computer computer;
229        struct og_dbi *dbi;
230        const char *key;
231        json_t *value;
232        int err = 0;
233        bool res;
234
235        if (json_typeof(data) != JSON_OBJECT)
236                return -1;
237
238        json_object_foreach(data, key, value) {
239                if (!strcmp(key, "software"))
240                        err = og_json_parse_string(value, &software);
241                else if (!strcmp(key, "partition"))
242                        err = og_json_parse_string(value, &partition);
243                else
244                        return -1;
245
246                if (err < 0)
247                        return -1;
248        }
249
250        if (!software || !partition) {
251                syslog(LOG_ERR, "malformed response json\n");
252                return -1;
253        }
254
255        err = og_dbi_get_computer_info(&computer, cli->addr.sin_addr);
256        if (err < 0)
257                return -1;
258
259        snprintf(legacy.software, sizeof(legacy.software), "%s", software);
260        snprintf(legacy.part, sizeof(legacy.part), "%s", partition);
261        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
262        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
263
264        dbi = og_dbi_open(&dbi_config);
265        if (!dbi) {
266                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
267                       __func__, __LINE__);
268                return -1;
269        }
270
271        res = actualizaSoftware(dbi, legacy.software, legacy.part, legacy.id,
272                                computer.name, legacy.center);
273        og_dbi_close(dbi);
274
275        if (!res) {
276                syslog(LOG_ERR, "Problem updating client configuration\n");
277                return -1;
278        }
279
280        return 0;
281}
282
283#define OG_PARAMS_RESP_REFRESH  (OG_PARAM_PART_DISK |           \
284                                 OG_PARAM_PART_NUMBER |         \
285                                 OG_PARAM_PART_CODE |           \
286                                 OG_PARAM_PART_FILESYSTEM |     \
287                                 OG_PARAM_PART_OS |             \
288                                 OG_PARAM_PART_SIZE |           \
289                                 OG_PARAM_PART_USED_SIZE)
290
291static int og_json_parse_partition_array(json_t *value,
292                                         struct og_partition *partitions)
293{
294        json_t *element;
295        int i, err;
296
297        if (json_typeof(value) != JSON_ARRAY)
298                return -1;
299
300        for (i = 0; i < json_array_size(value) && i < OG_PARTITION_MAX; i++) {
301                element = json_array_get(value, i);
302
303                err = og_json_parse_partition(element, &partitions[i],
304                                              OG_PARAMS_RESP_REFRESH);
305                if (err < 0)
306                        return err;
307        }
308
309        return 0;
310}
311
312static int og_dbi_queue_autorun(uint32_t computer_id, uint32_t proc_id)
313{
314        struct og_task dummy_task = {
315                .scope          = computer_id,
316                .type_scope     = AMBITO_ORDENADORES,
317                .procedure_id   = proc_id,
318        };
319        struct og_dbi *dbi;
320
321        dbi = og_dbi_open(&dbi_config);
322        if (!dbi) {
323                syslog(LOG_ERR, "cannot open connection database "
324                                "(%s:%d)\n", __func__, __LINE__);
325                return -1;
326        }
327        if (og_dbi_queue_procedure(dbi, &dummy_task)) {
328                og_dbi_close(dbi);
329                return -1;
330        }
331        og_dbi_close(dbi);
332
333        return 0;
334}
335
336static int og_resp_refresh(json_t *data, struct og_client *cli)
337{
338        struct og_partition partitions[OG_PARTITION_MAX] = {};
339        const char *serial_number = NULL;
340        struct og_computer computer = {};
341        struct og_partition disk_setup;
342        char cfg[1024] = {};
343        struct og_dbi *dbi;
344        const char *key;
345        unsigned int i;
346        json_t *value;
347        int err = 0;
348        bool res;
349
350        if (json_typeof(data) != JSON_OBJECT)
351                return -1;
352
353        json_object_foreach(data, key, value) {
354                if (!strcmp(key, "disk_setup")) {
355                        err = og_json_parse_partition(value,
356                                                      &disk_setup,
357                                                      OG_PARAMS_RESP_REFRESH);
358                } else if (!strcmp(key, "partition_setup")) {
359                        err = og_json_parse_partition_array(value, partitions);
360                } else if (!strcmp(key, "serial_number")) {
361                        err = og_json_parse_string(value, &serial_number);
362                } else {
363                        return -1;
364                }
365
366                if (err < 0)
367                        return err;
368        }
369
370        err = og_dbi_get_computer_info(&computer, cli->addr.sin_addr);
371        if (err < 0)
372                return -1;
373
374        if (strlen(serial_number) > 0)
375                snprintf(cfg, sizeof(cfg), "ser=%s\n", serial_number);
376
377        if (!disk_setup.disk || !disk_setup.number || !disk_setup.code ||
378            !disk_setup.filesystem || !disk_setup.os || !disk_setup.size ||
379            !disk_setup.used_size)
380                return -1;
381
382        snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
383                 "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
384                 disk_setup.disk, disk_setup.number, disk_setup.code,
385                 disk_setup.filesystem, disk_setup.os, disk_setup.size,
386                 disk_setup.used_size);
387
388        for (i = 0; i < OG_PARTITION_MAX; i++) {
389                if (!partitions[i].disk || !partitions[i].number ||
390                    !partitions[i].code || !partitions[i].filesystem ||
391                    !partitions[i].os || !partitions[i].size ||
392                    !partitions[i].used_size)
393                        continue;
394
395                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
396                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
397                         partitions[i].disk, partitions[i].number,
398                         partitions[i].code, partitions[i].filesystem,
399                         partitions[i].os, partitions[i].size,
400                         partitions[i].used_size);
401        }
402
403        dbi = og_dbi_open(&dbi_config);
404        if (!dbi) {
405                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
406                                  __func__, __LINE__);
407                return -1;
408        }
409        res = actualizaConfiguracion(dbi, cfg, computer.id);
410        og_dbi_close(dbi);
411
412        if (!res) {
413                syslog(LOG_ERR, "Problem updating client configuration\n");
414                return -1;
415        }
416
417        if (!cli->autorun && computer.procedure_id) {
418                cli->autorun = true;
419
420                if (og_dbi_queue_autorun(computer.id, computer.procedure_id))
421                        return -1;
422        }
423
424        return 0;
425}
426
427static int og_resp_image_create(json_t *data, struct og_client *cli)
428{
429        struct og_software_legacy soft_legacy;
430        struct og_image_legacy img_legacy;
431        const char *partition = NULL;
432        const char *software = NULL;
433        const char *image_id = NULL;
434        struct og_computer computer;
435        const char *disk = NULL;
436        const char *code = NULL;
437        const char *name = NULL;
438        const char *repo = NULL;
439        struct og_dbi *dbi;
440        const char *key;
441        json_t *value;
442        int err = 0;
443        bool res;
444
445        if (json_typeof(data) != JSON_OBJECT)
446                return -1;
447
448        json_object_foreach(data, key, value) {
449                if (!strcmp(key, "software"))
450                        err = og_json_parse_string(value, &software);
451                else if (!strcmp(key, "partition"))
452                        err = og_json_parse_string(value, &partition);
453                else if (!strcmp(key, "disk"))
454                        err = og_json_parse_string(value, &disk);
455                else if (!strcmp(key, "code"))
456                        err = og_json_parse_string(value, &code);
457                else if (!strcmp(key, "id"))
458                        err = og_json_parse_string(value, &image_id);
459                else if (!strcmp(key, "name"))
460                        err = og_json_parse_string(value, &name);
461                else if (!strcmp(key, "repository"))
462                        err = og_json_parse_string(value, &repo);
463                else
464                        return -1;
465
466                if (err < 0)
467                        return err;
468        }
469
470        if (!software || !partition || !disk || !code || !image_id || !name ||
471            !repo) {
472                syslog(LOG_ERR, "malformed response json\n");
473                return -1;
474        }
475
476        err = og_dbi_get_computer_info(&computer, cli->addr.sin_addr);
477        if (err < 0)
478                return -1;
479
480        snprintf(soft_legacy.center, sizeof(soft_legacy.center), "%d",
481                 computer.center);
482        snprintf(soft_legacy.software, sizeof(soft_legacy.software), "%s",
483                 software);
484        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
485                 image_id);
486        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
487        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
488        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
489        snprintf(img_legacy.code, sizeof(img_legacy.code), "%s", code);
490        snprintf(img_legacy.name, sizeof(img_legacy.name), "%s", name);
491        snprintf(img_legacy.repo, sizeof(img_legacy.repo), "%s", repo);
492
493        dbi = og_dbi_open(&dbi_config);
494        if (!dbi) {
495                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
496                       __func__, __LINE__);
497                return -1;
498        }
499
500        res = actualizaSoftware(dbi,
501                                soft_legacy.software,
502                                img_legacy.part,
503                                soft_legacy.id,
504                                computer.name,
505                                soft_legacy.center);
506        if (!res) {
507                og_dbi_close(dbi);
508                syslog(LOG_ERR, "Problem updating client configuration\n");
509                return -1;
510        }
511
512        res = actualizaCreacionImagen(dbi,
513                                      img_legacy.image_id,
514                                      img_legacy.disk,
515                                      img_legacy.part,
516                                      img_legacy.code,
517                                      img_legacy.repo,
518                                      soft_legacy.id);
519        og_dbi_close(dbi);
520
521        if (!res) {
522                syslog(LOG_ERR, "Problem updating client configuration\n");
523                return -1;
524        }
525
526        return 0;
527}
528
529static int og_resp_image_restore(json_t *data, struct og_client *cli)
530{
531        struct og_software_legacy soft_legacy;
532        struct og_image_legacy img_legacy;
533        const char *partition = NULL;
534        const char *image_id = NULL;
535        struct og_computer computer;
536        const char *disk = NULL;
537        dbi_result query_result;
538        struct og_dbi *dbi;
539        const char *key;
540        json_t *value;
541        int err = 0;
542        bool res;
543
544        if (json_typeof(data) != JSON_OBJECT)
545                return -1;
546
547        json_object_foreach(data, key, value) {
548                if (!strcmp(key, "partition"))
549                        err = og_json_parse_string(value, &partition);
550                else if (!strcmp(key, "disk"))
551                        err = og_json_parse_string(value, &disk);
552                else if (!strcmp(key, "image_id"))
553                        err = og_json_parse_string(value, &image_id);
554                else
555                        return -1;
556
557                if (err < 0)
558                        return err;
559        }
560
561        if (!partition || !disk || !image_id) {
562                syslog(LOG_ERR, "malformed response json\n");
563                return -1;
564        }
565
566        err = og_dbi_get_computer_info(&computer, cli->addr.sin_addr);
567        if (err < 0)
568                return -1;
569
570        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
571                 image_id);
572        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
573        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
574        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
575
576        dbi = og_dbi_open(&dbi_config);
577        if (!dbi) {
578                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
579                       __func__, __LINE__);
580                return -1;
581        }
582
583        query_result = dbi_conn_queryf(dbi->conn,
584                                       "SELECT idperfilsoft FROM imagenes "
585                                       " WHERE idimagen='%s'",
586                                       image_id);
587        if (!query_result) {
588                og_dbi_close(dbi);
589                syslog(LOG_ERR, "failed to query database\n");
590                return -1;
591        }
592        if (!dbi_result_next_row(query_result)) {
593                dbi_result_free(query_result);
594                og_dbi_close(dbi);
595                syslog(LOG_ERR, "software profile does not exist in database\n");
596                return -1;
597        }
598        snprintf(img_legacy.software_id, sizeof(img_legacy.software_id),
599                 "%d", dbi_result_get_uint(query_result, "idperfilsoft"));
600        dbi_result_free(query_result);
601
602        res = actualizaRestauracionImagen(dbi,
603                                          img_legacy.image_id,
604                                          img_legacy.disk,
605                                          img_legacy.part,
606                                          soft_legacy.id,
607                                          img_legacy.software_id);
608        og_dbi_close(dbi);
609
610        if (!res) {
611                syslog(LOG_ERR, "Problem updating client configuration\n");
612                return -1;
613        }
614
615        return 0;
616}
617
618int og_agent_state_process_response(struct og_client *cli)
619{
620        json_error_t json_err;
621        json_t *root;
622        int err = -1;
623        char *body;
624
625        if (!strncmp(cli->buf, "HTTP/1.0 202 Accepted",
626                     strlen("HTTP/1.0 202 Accepted"))) {
627                og_dbi_update_action(cli->last_cmd_id, true);
628                cli->last_cmd_id = 0;
629                return 1;
630        }
631
632        if (strncmp(cli->buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) {
633                og_dbi_update_action(cli->last_cmd_id, false);
634                cli->last_cmd_id = 0;
635                return -1;
636        }
637        og_dbi_update_action(cli->last_cmd_id, true);
638        cli->last_cmd_id = 0;
639
640        if (!cli->content_length) {
641                cli->last_cmd = OG_CMD_UNSPEC;
642                return 0;
643        }
644
645        body = strstr(cli->buf, "\r\n\r\n") + 4;
646
647        root = json_loads(body, 0, &json_err);
648        if (!root) {
649                syslog(LOG_ERR, "%s:%d: malformed json line %d: %s\n",
650                       __FILE__, __LINE__, json_err.line, json_err.text);
651                return -1;
652        }
653
654        switch (cli->last_cmd) {
655        case OG_CMD_PROBE:
656                err = og_resp_probe(cli, root);
657                break;
658        case OG_CMD_SHELL_RUN:
659                err = og_resp_shell_run(cli, root);
660                break;
661        case OG_CMD_HARDWARE:
662                err = og_resp_hardware(root, cli);
663                break;
664        case OG_CMD_SOFTWARE:
665                err = og_resp_software(root, cli);
666                break;
667        case OG_CMD_REFRESH:
668                err = og_resp_refresh(root, cli);
669                break;
670        case OG_CMD_SETUP:
671                err = og_resp_refresh(root, cli);
672                break;
673        case OG_CMD_IMAGE_CREATE:
674                err = og_resp_image_create(root, cli);
675                break;
676        case OG_CMD_IMAGE_RESTORE:
677                err = og_resp_image_restore(root, cli);
678                break;
679        default:
680                err = -1;
681                break;
682        }
683
684        cli->last_cmd = OG_CMD_UNSPEC;
685
686        return err;
687}
Note: See TracBrowser for help on using the repository browser.